improving apps with ios 10 notifications (do ios 2016)
TRANSCRIPT
1
Hi, I’m Donny
Improving apps with iOS 10 notificationsBecause notifications can be pretty cool
2
ContentsA quick history of notifications
Introduction to the UserNotifications framework
Service Extensions
Content Extensions
The bigger picture
iOS 7Text only notifications
Limited information and context
iOS 8Simple actions
Apple had a Text Input action for quick replies
iOS 9Developers could add the Text Input action
Less need to open the app
Everything < iOS 10
The difference between local and remote
func application(_ application: UIApplication, didReceiveRemoteNotification userInfo: [AnyHashable : Any]) { }
func application(_ application: UIApplication, didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data) { }
func application(_ application: UIApplication, didReceive notification: UILocalNotification) { }
func application(_ application: UIApplication, didRegister notificationSettings: UIUserNotificationSettings) { }
Everything < iOS 10
And of course, it all goes in AppDelegate
func application(_ application: UIApplication, didReceiveRemoteNotification userInfo: [AnyHashable : Any]) { }
func application(_ application: UIApplication, didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data) { }
func application(_ application: UIApplication, didReceive notification: UILocalNotification) { }
func application(_ application: UIApplication, didRegister notificationSettings: UIUserNotificationSettings) { }
Everything < iOS 10
Showing notifications while foregroundedThere’s one more thing…
iOS 10Media in notifications
Custom user interface
True end-to-end encryption
Unified framework
UserNotification at a glance
Unified Local and Remote
Single registration handler
Handle notifications through a delegate
Not compatible with < iOS 10
func userNotificationCenter(_ center: UNUserNotificationCenter, didReceive response: UNNotificationResponse, withCompletionHandler completionHandler: @escaping () -> Void) {
}
func userNotificationCenter(_ center: UNUserNotificationCenter, willPresent notification: UNNotification, withCompletionHandler completionHandler: @escaping (UNNotificationPresentationOptions) -> Void) { }
let notificationCenter = UNUserNotificationCenter.current() notificationCenter.getNotificationSettings { settings in if settings.authorizationStatus == .notDetermined { notificationCenter.requestAuthorization(options: [.badge, .alert]) { success, error in // handle status } } }
UserNotification at a glance
UIApplication.shared.registerForRemoteNotifications() APNSfunc application(_ application: UIApplication, didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data) { }
UserNotification at a glancelet content = UNMutableNotificationContent() content.title = “Next speaker"content.body = “Donny is up next" content.badge = 1
let path = Bundle.main.path(forResource: "thumbs", ofType: "png")! let imageUrl = URL(fileURLWithPath: path) let image = try! UNNotificationAttachment(identifier: "thumbs-up", url: imageUrl, options: nil) content.attachments = [image]
let trigger = UNTimeIntervalNotificationTrigger(timeInterval: 10, repeats: false) let request = UNNotificationRequest(identifier: “nextSpeaker", content: content, trigger: trigger)
notificationCenter.add(request, withCompletionHandler: nil)
Create notification contents
Schedule the notification
Update notification contents
UserNotification at a glance
Create notification contents
Schedule the notification
Update notification contents
And when you're in the foreground...
func userNotificationCenter(_ center: UNUserNotificationCenter, willPresent notification: UNNotification, withCompletionHandler completionHandler: @escaping (UNNotificationPresentationOptions) -> Void) { completionHandler([.alert, .sound]) }
Service extensions
Hey there! What's up?
49 29b9 cfdc15cfe 3969 107fa
Service Extension
End to end encryption
Send push with mutable-content: 1
Update contents
Limited time available
Service extensionsoverride func didReceive(_ request: UNNotificationRequest, withContentHandler contentHandler: @escaping (UNNotificationContent) -> Void) { self.contentHandler = contentHandler decryptedContent = (request.content.mutableCopy() as? UNMutableNotificationContent) if let decryptedContent = decryptedContent { decryptedContent.title = "Updated title" contentHandler(decryptedContent) } }
override func serviceExtensionTimeWillExpire() { if let contentHandler = contentHandler, let decryptedContent = decryptedContent { contentHandler(decryptedContent) } }
End to end encryption
Send push with mutable-content: 1
Update contents
Limited time available
Content extensionsView controller based extension
Extensions are tied to categories
Set content ratio in .plist
Actions are to added to notifications separately
<key>NSExtensionAttributes</key> <dict> <key>UNNotificationExtensionCategory</key> <string>wheel</string> <key>UNNotificationExtensionInitialContentSizeRatio</key> <real>1</real> </dict>
let content = UNMutableNotificationContent() content.title = "Spin the wheel?" content.body = "Win tickets for Do iOS" content.categoryIdentifier = "wheel" content.badge = 1
Content extensionsBring your own UI
Extensions don’t receive touches
Extensions do receive notification responses
Even less need for users to open your app
func didReceive(_ response: UNNotificationResponse, completionHandler completion: @escaping (UNNotificationContentExtensionResponseOption) -> Void) { if response.actionIdentifier == "spin" { wheel.spin() } }
Looking at the bigger picture
Stand out with Content Extensions
Design for short, quick interactions
Increased privacy with Service Extensions
Hey there! What's up?
49 29b9 cfdc15cfe 3969 107fa
Service Extension
Looking at the bigger picture
Cleaner code, more maintainable
Only send meaningful messages
Use identifiers to update notifications if needed
Thank you