iOS 10 UNUserNotificationCenterDelegate Overview

I just finished watching “Introduction to Notifications” from WWDC 2016 and there are some really cool new features for iOS 10 local notifications. Notifications are core to the mobile experience, regardless of what platform you’re using – Android, iOS, or something else. Apple really raised the bar with their iOS 10 local notifications through creation of a new framework, the User Notifications framework. The brand new iOS 10 UNUserNotificationCenterDelegate in the User Notifications Framework is one thing that jumped out at me.

Why Create A New Framework?

Push notifications have been available in iOS for years. Just like any framework, over time, as use cases and technology evolves, frameworks need to be reconsidered and improved. It is that time for push notifications on iOS. New in iOS 10, Apple created the User Notifications Framework. When implementing notifications, you have the choice to implement a local or remote notification. A local notification does not require a server to alert the user, where a remote notification does require a remote server to send information to the user. In past iOS versions, depending on the type of notification you are handling, there are two different methods in UIApplicationDelegate to implement to handle either notification type – remote or local. As such, this can lead to a lot of duplicate code since it’s likely that there is common handling of notifications regardless of whether they are local or remote.

One Notification Handler To Rule Them All

The User Notification Framework in iOS 10 fixes this as there is now a single method for handling both types of notifications. The new iOS 10 UNUserNotificationCenterDelegate now has a single set of methods for handling both remote and local notifications.

Deprecated

The old methods on UIApplicationDelegate are deprecated, including:

  • application(_:didReceive:) – Sent to the delegate when a running app receives a local notification.
  • application(_:didReceiveRemoteNotification:) – Called when your app has received a remote notification
  • application(_:handleActionWithIdentifier:forRemoteNotification:completionHandler:) – Tells the app delegate to perform the custom action specified by a remote notification.
  • application(_:handleActionWithIdentifier:for:withResponseInfo:completionHandler:) – Called when your app has been activated by the user selecting an action from a local notification.
  • application(_:handleActionWithIdentifier:forRemoteNotification:withResponseInfo:completionHandler:) – Called when your app has been activated by the user selecting an action from a remote notification.

New

Instead, these are all consolidated into a TWO METHODS in the new iOS 10 UNUserNotificationCenterDelegate protocol:

  • userNotificationCenter(_:didReceive:withCompletionHandler:) – Called to let your app know which action was selected by the user for a given notification.
  • userNotificationCenter(_:willPresent:withCompletionHandler:) – Delivers a notification to an app running in the foreground.

That’s right, two methods. And what’s better, is that now that they are moved into their own protocol, the iOS 10 UNUserNotificationCenterDelegate so this will help clean up your existing UIApplicationDelegate by being able to refactor all that old notification handling code into a shiny, new, cohesive protocol of it’s own.

Here’s an example:

extension NotificationManager: UNUserNotificationCenterDelegate {

    func userNotificationCenter(_ center: UNUserNotificationCenter, didReceive response: UNNotificationResponse, withCompletionHandler completionHandler: () -> Void) {

        switch response.actionIdentifier {

        // NotificationActions is a custom String enum I've defined
        case NotificationActions.HighFive.rawValue:
            print("High Five Delivered!")
        default: break
        }
    }

    func userNotificationCenter(_ center: UNUserNotificationCenter, willPresent notification: UNNotification, withCompletionHandler completionHandler: (UNNotificationPresentationOptions) -> Void) {

        // Delivers a notification to an app running in the foreground.
    }
}

That’s literally it for handling notifications.

Bonus: Creating Local Notifications

Similar, creating local notifications has also been simplified. In order to verify the behavior of the new iOS 10 UNUserNotificationCenterDelegate protocol, I wrote some sample iOS 10 User Notifications Framework code to generate a local notification:

// 1
let highFiveAction = UNNotificationAction(identifier: NotificationActions.HighFive.rawValue, title: "High Five", options: [])
let category = UNNotificationCategory(identifier: "wassup", actions: [highFiveAction], minimalActions: [highFiveAction], intentIdentifiers: [], options: [.customDismissAction])
UNUserNotificationCenter.current().setNotificationCategories([category])

// 2
let highFiveContent = UNMutableNotificationContent()
highFiveContent.title = "Wassup?"
highFiveContent.body = "Can I get a high five?"

// 3
let trigger = UNTimeIntervalNotificationTrigger(timeInterval: 5, repeats: false)

// 4
let highFiveRequestIdentifier = "sampleRequest"
let highFiveRequest = UNNotificationRequest(identifier: highFiveRequestIdentifier, content: highFiveContent, trigger: trigger)
UNUserNotificationCenter.current().add(highFiveRequest) { (error) in
  // handle the error if needed
  print(error)
}

Here’s an overview of that code block:

  1. Create the custom “High Five” action for responding to the local notification, and set it as a category for the notification in addition to a system provided category for simply “dismissing” the notification.
  2. Create the content for the local notification.
  3. Create the trigger for the notification, for it to pop 5 seconds in the future.
  4. Add the notification to the notification system.

This code highlights two new features of local notifications in iOS 10, custom actions and time based triggers.

Custom actions now let you specify any number of actions for which the end user may respond to the notification.

iOS 10 UNUserNotificationCenterDelegate

Time based triggers allow you to delay the local notification by a time interval, designate it as repeating or not, and even schedule it based on an actual date.

I didn’t hear it confirmed in the WWDC presentation, but I’m pretty sure that the custom notification actions require 3D Touch. I could not figure out how to interact with them on my iPhone 5s device that is running iOS 10.

I’ve even bundled all this code up into an Xcode project for you on GitHub, here.

Notify Me

Notifications, remote and local, enable some of my favorite features on iOS so as an end user, I’m happy to see all these enhancements. As a developer, I can’t wait to try them out in my own app. This only scratches the surface of the new stuff Apple added. Do you use notifications in your app? What are you looking forward to most about the new iOS 10 User Notifications Framework? What about the iOS 10 UNUserNotificationCenterDelegate?

Happy cleaning.