Notifications in iOS 10
With iOS 10, tvOS 10 and watchOS 3 launch Apple introduced the new UserNotifications
framework. It supports the delivery and handling of local and remote notifications. Cool, but you can say that it was already possible through UIKit
and classes like UILocalNotification
or dictionaries for remote notifications. And you’re completely right, but these new possibilities, in particular, are extremely convenient and powerful. Take a look at it with me!
Let’s start with a little disclaimer: the new framework works great if you target your app for iOS 10 or newer. Otherwise, you have to use deprecated objects or implement it twice for iOS older and newer than 10.0. You can do this like that:
1 2 3 4 5 | if #available(iOS 10.0, *) { // UserNotifications framework here } else { // Old implementation here } |
Okay, now when we know everything about the limitations, we can start with these shiny new features.
Notification state
Before you schedule the very first local notification, you should register your app for receiving user notifications at all.
First, remember to import UserNotifications
. Then request authorization through the UNUserNotificationCenter
singleton object.
1 2 3 4 5 6 7 | import UserNotifications func requestAuthorization() { UNUserNotificationCenter.current().requestAuthorization(options: [.alert, .sound, .badge]) { (granted, error) in print("Access granted: \(granted.description)") } } |
I guess that you’ve already noticed that the new framework gives you information about the authorization status just after authorization. That’s something that was missing in the elder framework. You can also get even more precise status thanks to getNotificationSettings:
.
1 2 3 4 5 6 | UNUserNotificationCenter.current().getNotificationSettings { notificationSettings in let status = notificationSettings.authorizationStatus let sound = notificationSettings.soundSetting let badge = notificationSettings.badgeSetting let alert = notificationSettings.alertSetting } |
The notificationSettings
is an UNNotificationSettings
object, which contains multiple enums giving the current status of an app notification settings. It’s pretty straightforward and let you do things that were not allowed in iOS 9.
Triggers
iOS 9 and elder don’t let you easily set repeating local notification. Fortunately, there were little libraries like our in-company Habit making this a bit easier.
iOS 10 notifications use simple and powerful triggering mechanism. Let’s say you need an event that fires every hour. You can achieve that doing this:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 | // 1) Create a notification content let notificationContent = UNMutableNotificationContent() notificationContent.title = "Droids On Roids" // 2) Create a DateComponents for every o'clock hour var dateComponents = DateComponents() dateComponents.minute = 0 dateComponents.second = 0 // 3) Create a trigger based on the matching date let trigger = UNCalendarNotificationTrigger(dateMatching: dateComponents, repeats: true) // 4) Create a request with the given identifier content and trigger let request = UNNotificationRequest(identifier: "myNotification", content: notificationContent, trigger: trigger) // 5) Add the request to the UserNotificationCenter UNUserNotificationCenter.current().add(request) { error in guard let error = error else { return } print(error.localizedDescription) } |
Boring? What about a trigger based on location? This technique is used by Reminders.app and in iOS 10 it can look like this:
1 2 3 | let droidsOnRoidsCoordinate = CLLocationCoordinate2D(latitude: 51.108989, longitude: 17.029211) let region = CLCircularRegion(center: droidsOnRoidsCoordinate, radius: 100.0, identifier: "Droids On Roids, pl. Solny 15, Wrocław") let locationTrigger = UNLocationNotificationTrigger(region: region, repeats: false) |
Then just use this trigger the same as in the previous example and you’ll receive a notification when to find yourself in 100 meters radius from our office!
Push notifications
You can use UNUserNotificationCenter
‘s delegate to receive and handle push (and local – if you want) notifications.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 | import UserNotifications @UIApplicationMain class AppDelegate: UIResponder, UIApplicationDelegate { var window: UIWindow? func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool { UNUserNotificationCenter.current().delegate = self return true } } extension AppDelegate: UNUserNotificationCenterDelegate { func userNotificationCenter(_ center: UNUserNotificationCenter, didReceive response: UNNotificationResponse, withCompletionHandler completionHandler: @escaping () -> Void) { if response.notification.request.trigger is UNPushNotificationTrigger { // Do something with received push notification (response.notification) } completionHandler() } } |
Actions
iOS 10 notifications offer custom action. In the example, you can get a notification from your clinic about an upcoming visit and agree (confirm) or decline (resign) the term even without opening the app.
I’ve got a much simpler example with the action that doesn’t like to be tapped and if you’re stubborn, printing you boring lorem ipsum.
1 2 3 | let action = UNNotificationAction(identifier: "pleaseDoNotTap", title: "DON'T TAP ME", options: .destructive) let category = UNNotificationCategory(identifier: "category", actions: [action], intentIdentifiers: [], options: .customDismissAction) UNUserNotificationCenter.current().setNotificationCategories([category]) |
It’s all about setting notification categories with actions. In the example, I use only one category with one action inside. Then just set categoryIdentifier
of your UNNotificationContent
to the proper identifier.
1 2 | UNUserNotificationCenter.current().delegate = self notificationContent.categoryIdentifier = "category" |
I also set up a delegate to the current view controller, because it works thank to userNotificationCenter(_:didReceive:withCompletionHandler:)
method too.
1 2 3 4 5 6 7 8 9 | func userNotificationCenter(_ center: UNUserNotificationCenter, didReceive response: UNNotificationResponse, withCompletionHandler completionHandler: @escaping () -> Void) { if response.actionIdentifier == "pleaseDoNotTap" { print("=== I SAID NO! ===") print("Read >> Lorem ipsum << as a punish!") print(loremIpsum) } completionHandler() } |
UserNotificationsUI
I guess that’s not all about UserNotifications
, but there is also UserNotificationsUI
, which lets you customise the appearance of local and remote notifications. iOS 10 gives you the great opportunity to update your apps and many of us already did it (according to appreviewtimes.com average review time has increased from 1 to 3 days and I don’t think that’s because Apple fired some reviewers ;)). Why do not implement new notifications right now?
You can find the complete source code on Droids on Roids’s GitHub repository.
About the author
Ready to take your business to the next level with a digital product?
We'll be with you every step of the way, from idea to launch and beyond!