Notify Me, Notify You. Aha!

Ddd6d3bac7772fa67fc5e312a18bdaec?s=47 sammyd
October 19, 2016

Notify Me, Notify You. Aha!

User Notifications in iOS 10

User notifications are incredibly important part of iOS apps - allowing you to get your user to interact with your app when *you* want. They enrich the user experience, and provide real value to your users. So why are they such a pain to work with? Apple has finally heard your cries of despair, and in iOS 10 introduces the new UserNotifications framework. This acts as a central place to handle all user notifications, whether they be local or push notifications.

In this talk we'll take a quick jaunt through the new framework, covering what you need to do to transition existing behaviour, in addition to looking at some of the new functionality. Learn how to create custom, interactive notifications, as well as building an extension to intercept and manipulate your push notifications. There may well be additional ABBA puns, but given the quality of the first one, it's looking unlikely.

Ddd6d3bac7772fa67fc5e312a18bdaec?s=128

sammyd

October 19, 2016
Tweet

Transcript

  1. Notify Me, Notify You. Aha! User notifications in iOS 10

    Sam Davies @iwantmyrealname
  2. hi, i'm sam

  3. What are user notifications?

  4. Not to be confused with notification centre

  5. Problems with ye olde way — Conflated source and display

    — Operating in a vacuum — Evolved not designed — Manual in-app display
  6. The UserNotifications Framework — Fixes the issues — Query for

    permission status — Management of local notifications — Custom UI — Mutate push notifications
  7. Authorisation

  8. Authorisation — Very similar to other iOS authorisation requests —

    Doesn't require Info.plist usage string — Still have to request for remote notifications
  9. Authorisation UNUserNotificationCenter .current() .requestAuthorization(options: [.alert, .sound]) { (granted, error) in

    if granted { self.loadNotificationData() } else { print(error?.localizedDescription) } }
  10. Authorisation open class UNUserNotificationCenter : NSObject { ... open func

    getNotificationSettings(completionHandler: @escaping (UNNotificationSettings) -> ()) ... }
  11. demo

  12. Scheduling

  13. Scheduling — Push notifications — Time interval — Calendar —

    Geofence
  14. Notification Content let attachment = try! UNNotificationAttachment(identifier: randomImageName, url: imageURL,

    options: .none) let content = UNMutableNotificationContent() content.title = "New cuddlePix!" content.subtitle = "What a treat" content.attachments = [attachment] content.body = "Cheer yourself up with a hug !" content.categoryIdentifier = newCuddlePixCategoryName //content.threadIdentifier = "my-conversation-thread"
  15. Triggers & Requests let trigger = UNTimeIntervalNotificationTrigger(timeInterval: inSeconds, repeats: false)

    let request = UNNotificationRequest(identifier: randomImageName, content: content, trigger: trigger) UNUserNotificationCenter .current() .add(request, withCompletionHandler: { (error) in if let error = error { print(error) } completion() })
  16. Management

  17. Management open class UNUserNotificationCenter : NSObject { ... // PENDING

    open func getPendingNotificationRequests( completionHandler: @escaping ([UNNotificationRequest]) -> ()) open func removePendingNotificationRequests( withIdentifiers identifiers: [String]) open func removeAllPendingNotificationRequests() ...
  18. Management ... // DELIVERED open func getDeliveredNotifications( completionHandler: @escaping ([UNNotification])

    -> ()) open func removeDeliveredNotifications( withIdentifiers identifiers: [String]) open func removeAllDeliveredNotifications() }
  19. In-App Delivery

  20. In-App Delivery UNUserNotificationCenter.current().delegate = self Implement the delegate method: func

    userNotificationCenter(_ center: UNUserNotificationCenter, willPresent notification: UNNotification, withCompletionHandler completionHandler: @escaping (UNNotificationPresentationOptions) -> Swift.Void { completionHandler(.alert) }
  21. In-App Delivery UNUserNotificationCenter.current().delegate = self Implement the delegate method: func

    userNotificationCenter( _ center: UNUserNotificationCenter, willPresent notification: UNNotification, withCompletionHandler completionHandler: @escaping (UNNotificationPresentationOptions) -> ()) { completionHandler(.alert) }
  22. demo

  23. Custom UI

  24. Custom UI — New extension type in iOS 10 —

    Provided a storyboard & a view controller — UNNotificationContentExtension provides notification
  25. Custom UI — Notification contains request — Attachments aren't readily

    available to your extension func didReceive(_ notification: UNNotification) { if let attachment = notification.request.content.attachments.first { if attachment.url.startAccessingSecurityScopedResource() { let imageData = try? Data(contentsOf: attachment.url) if let imageData = imageData { imageView.image = UIImage(data: imageData) } attachment.url.stopAccessingSecurityScopedResource() } } }
  26. Interactivity

  27. Interactivity func didReceive( _ response: UNNotificationResponse, completionHandler completion: @escaping (UNNotificationContentExtensionResponseOption)

    -> ()) { if response.actionIdentifier == "star" { showStars() } let time = DispatchTime.now() + DispatchTimeInterval.milliseconds(2000) DispatchQueue.main.asyncAfter(deadline: time) { completion(.dismissAndForwardAction) } }
  28. demo

  29. Intercepting Push Notifications

  30. Intercepting push notifications — via the Service Extension point —

    Think of it as a .filter() operation — Provided with notification request—return content — Limited time to perform processing — Push notification must explicitly allow mutation
  31. Content augmentation override func didReceive(_ request: UNNotificationRequest, withContentHandler contentHandler: @escaping

    (UNNotificationContent) -> Void) { self.contentHandler = contentHandler bestAttemptContent = (request.content.mutableCopy() as? UNMutableNotificationContent) if let bestAttemptContent = bestAttemptContent { if let attachmentString = bestAttemptContent.userInfo["attachment-url"] as? String, let attachmentUrl = URL(string: attachmentString) { // Do some downloading ... let attachment = try! UNNotificationAttachment(identifier: attachmentString, url: url, options: [UNNotificationAttachmentOptionsTypeHintKey : kUTTypePNG]) bestAttemptContent.attachments = [attachment] contentHandler(bestAttemptContent) } } }
  32. Handling timeout override func serviceExtensionTimeWillExpire() { if let contentHandler =

    contentHandler, let bestAttemptContent = bestAttemptContent { contentHandler(bestAttemptContent) } }
  33. demo

  34. Summary — Central place for all (user) notification goodness —

    Can query settings and manage enqueued local notifications — Extend user experience with custom notification UI — Enhance push notifications with service extensions
  35. Make the switch if you can

  36. ! Links videos.raywenderlich.com developer.apple.com/wwdc16/707 developer.apple.com/wwdc16/708 developer.apple.com/reference/usernotifications github.com/sammyd @iwantmyrealname