Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Notify Me, Notify You. Aha!

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.

sammyd

October 19, 2016
Tweet

More Decks by sammyd

Other Decks in Programming

Transcript

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

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

    permission status — Management of local notifications — Custom UI — Mutate push notifications
  3. Authorisation — Very similar to other iOS authorisation requests —

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

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

    getNotificationSettings(completionHandler: @escaping (UNNotificationSettings) -> ()) ... }
  6. 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"
  7. 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() })
  8. Management open class UNUserNotificationCenter : NSObject { ... // PENDING

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

    -> ()) open func removeDeliveredNotifications( withIdentifiers identifiers: [String]) open func removeAllDeliveredNotifications() }
  10. 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) }
  11. In-App Delivery UNUserNotificationCenter.current().delegate = self Implement the delegate method: func

    userNotificationCenter( _ center: UNUserNotificationCenter, willPresent notification: UNNotification, withCompletionHandler completionHandler: @escaping (UNNotificationPresentationOptions) -> ()) { completionHandler(.alert) }
  12. Custom UI — New extension type in iOS 10 —

    Provided a storyboard & a view controller — UNNotificationContentExtension provides notification
  13. 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() } } }
  14. 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) } }
  15. 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
  16. 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) } } }
  17. Handling timeout override func serviceExtensionTimeWillExpire() { if let contentHandler =

    contentHandler, let bestAttemptContent = bestAttemptContent { contentHandler(bestAttemptContent) } }
  18. 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