Advanced Notifications

Similar documents
Using Grouped Notifications

Enhancing your apps for the next dimension of touch

What s New in imessage Apps

Using and Extending the Xcode Source Editor

Extending Your Apps with SiriKit

Implementing UI Designs in Interface Builder

Media and Gaming Accessibility

What s New in tvos #WWDC16. App Frameworks. Session 206. Hans Kim tvos Engineer

Cocoa Touch Best Practices

What s New in Notifications

What s New in MapKit. App Frameworks #WWDC17. Fredrik Olsson

Mastering UIKit on tvos

Getting the Most Out of HealthKit

Leveraging Touch Input on ios

What s New in tvos 12

What s New in watchos

What s New in Xcode App Signing

Quick Interaction Techniques for watchos

INTRODUCTION TO ARCHITECTING YOUR IOS APP

lecture 10 UI/UX and Programmatic Design cs : spring 2018

} override func didreceivememorywarning() { 26 super.didreceivememorywarning() 27 } 28 } Pause Stop

WatchKit In-Depth, Part 2

ios Memory Deep Dive #WWDC18 Kyle Howarth, Software Engineer James Snee, Software Engineer Kris Markel, Software Engineer

Data Delivery with Drag and Drop

Notifications. Mobile Application Development in ios School of EECS Washington State University Instructor: Larry Holder

Building Faster in Xcode

Building Apps with Dynamic Type

CarPlay Audio and Navigation Apps

What s New in Testing

Enabling Your App for CarPlay

Seamless Linking to Your App

Getting the Most out of Playgrounds in Xcode

Stanford CS193p. Developing Applications for ios. Winter CS193p. Winter 2017

App. Chapter 19 App. App (ViewController) App. Single View Application Single View Application View. (View Controller)

Introducing Password AutoFill for Apps

Creating Audio Apps for watchos

Advanced Scrollviews and Touch Handling Techniques

Stanford CS193p. Developing Applications for ios. Spring CS193p. Spring 2016

Building Watch Apps #WWDC15. Featured. Session 108. Neil Desai watchos Engineer

Introduction to Siri Shortcuts

App Extension Best Practices

ios Accessibility Developing for everyone Session 201 Ian Fisch ios Accessibility

imessage Apps and Stickers, Part 2

Advances in AVFoundation Playback

What s New in SiriKit

Monetize and Promote Your App with iad

What s New in CloudKit

Introducing On Demand Resources

Event Delivery: The Responder Chain

Stanford CS193p. Developing Applications for ios. Winter CS193p! Winter 2015

Building the App - Part 5 - Adding a Link

Engineering for Testability

Touch Bar Fundamentals

Gerontechnology II. Collecting Smart Phone Sensor Data for Gerontechnology. Using ios

Stanford CS193p. Developing Applications for ios. Fall CS193p. Fall

View Controllers CPRE 388

Mastering Drag and Drop

Lecture 8 Demo Code: Cassini Multithreading

Intro to Native ios Development. Dave Koziol Arbormoon Software, Inc.

CloudKit Tips And Tricks

News- ipad: ios(swift) Application

Mobile Development Lab 3

Rx in the real world. 1 Rob Ciolli

Getting Started with CareKit

New UIKit Support for International User Interfaces

Social Pinboard: ios(swift) Application

Managing Documents In Your ios Apps

What s New in Core Data?

Chapter 22 TableView TableView. TableView ios. ViewController. Cell TableViewCell TableView

UI Design and Storyboarding

Mobile Development - Lab 2

Introducing the Photos Frameworks

Introducing SiriKit. Hey Siri, say hello to apps #WWDC16. App Frameworks. Session 217

Stanford CS193p. Developing Applications for ios. Fall CS193p. Fall

Document Version Date: 1st March, 2015

Accessibility on OS X

A Mad Libs app that you will navigate through 3 UIViewControllers to add text that will be shown in a story on the fourth UIViewController.

What's New in Core Spotlight

Writing Energy Efficient Apps

What s New in SpriteKit

Patterns & practices for unit-testing Swift-ly. Jakub Turek 18th June, 2018

Building for Voice with Siri Shortcuts

High Performance Auto Layout

Types of Views. View category Purpose Examples of views. Display a particular type of content, such as an image or text.

Introducing the Contacts Framework

Integrating Apps and Content with AR Quick Look

Multitasking Support on the ios Platform

Modern User Interaction on ios

LESSONS LEARNED. SWIFT. Dagna Bieda, 7th April 2016

What s New in HomeKit

Announcements. Today s Topics

What s New in Core Image

Swift API Design Guidelines

Stanford CS193p. Developing Applications for ios. Fall CS193p. Fall

Mysteries of Auto Layout, Part 1

What s New in Cocoa for macos

Introducing PDFKit on ios

iphone Application Programming Lab 3: Swift Types and Custom Operator + A02 discussion

ITP 342 Mobile App Dev. Connections

Introducing MusicKit. Media #WWDC17. Tim Parthemore, MusicKit Services Joel Lopes Da Silva, ios Music

Transcription:

System Frameworks #WWDC16 Advanced Notifications Session 708 Michele Campeotto ios Notifications 2016 Apple Inc. All rights reserved. Redistribution or public display not permitted without written permission from Apple.

Agenda Notifications User Interface Media Attachments Customization

Notifications User Interface

Media Attachments

Media Attachments Push Payload

Media Attachments Push Payload { aps: { alert: {, mutable-content: 1 my-attachment: "https://example.com/photo.jpg"

Media Attachments Push Payload { aps: { alert: {, mutable-content: 1 my-attachment: "https://example.com/photo.jpg"

Media Attachments Push Payload { aps: { alert: {, mutable-content: 1 my-attachment: "https://example.com/photo.jpg"

Media Attachments Push Payload Service Extension

Media Attachments Push Payload Service Extension

// Adding an attachment to a user notification public class NotificationService: UNNotificationServiceExtension { override public func didreceive(_ request: UNNotificationRequest, withcontenthandler contenthandler: (UNNotificationContent) -> Void) { let fileurl = //... let attachment = UNNotificationAttachment(identifier: "image", url: fileurl, options: nil) let content = request.content.mutablecopy as! UNMutableNotificationContent content.attachments = [ attachment ] contenthandler(content)

// Adding an attachment to a user notification public class NotificationService: UNNotificationServiceExtension { override public func didreceive(_ request: UNNotificationRequest, withcontenthandler contenthandler: (UNNotificationContent) -> Void) { let fileurl = //... let attachment = UNNotificationAttachment(identifier: "image", url: fileurl, options: nil) let content = request.content.mutablecopy as! UNMutableNotificationContent content.attachments = [ attachment ] contenthandler(content)

// Adding an attachment to a user notification public class NotificationService: UNNotificationServiceExtension { override public func didreceive(_ request: UNNotificationRequest, withcontenthandler contenthandler: (UNNotificationContent) -> Void) { let fileurl = //... let attachment = UNNotificationAttachment(identifier: "image", url: fileurl, options: nil) let content = request.content.mutablecopy as! UNMutableNotificationContent content.attachments = [ attachment ] contenthandler(content)

// Adding an attachment to a user notification public class NotificationService: UNNotificationServiceExtension { override public func didreceive(_ request: UNNotificationRequest, withcontenthandler contenthandler: (UNNotificationContent) -> Void) { let fileurl = //... let attachment = UNNotificationAttachment(identifier: "image", url: fileurl, options: nil) let content = request.content.mutablecopy as! UNMutableNotificationContent content.attachments = [ attachment ] contenthandler(content)

// Adding an attachment to a user notification public class NotificationService: UNNotificationServiceExtension { override public func didreceive(_ request: UNNotificationRequest, withcontenthandler contenthandler: (UNNotificationContent) -> Void) { let fileurl = //... let attachment = UNNotificationAttachment(identifier: "image", url: fileurl, options: nil) let content = request.content.mutablecopy as! UNMutableNotificationContent content.attachments = [ attachment ] contenthandler(content)

// Adding an attachment to a user notification public class NotificationService: UNNotificationServiceExtension { override public func didreceive(_ request: UNNotificationRequest, withcontenthandler contenthandler: (UNNotificationContent) -> Void) { let fileurl = //... let attachment = UNNotificationAttachment(identifier: "image", url: fileurl, options: nil) let content = request.content.mutablecopy as! UNMutableNotificationContent content.attachments = [ attachment ] contenthandler(content)

Media Attachments

Media Attachments Local and remote notifications

Media Attachments Local and remote notifications Image, audio, video

Media Attachments Local and remote notifications Image, audio, video Download in the service extension

Media Attachments Local and remote notifications Image, audio, video Download in the service extension Limited processing time and size

Media Attachments Local and remote notifications Image, audio, video Download in the service extension Limited processing time and size Add attachment to notification

Media Attachments Local and remote notifications Image, audio, video Download in the service extension Limited processing time and size Add attachment to notification File is moved and managed by the system

Custom User Interface

Custom User Interface

Custom User Interface Notification content extension

Custom User Interface Notification content extension Custom views

Custom User Interface Notification content extension Custom views No interaction

Custom User Interface Notification content extension Custom views No interaction Respond to notification actions

Notification Content Extension

// Minimal Content Extension class NotificationViewController: UIViewController, UNNotificationContentExtension { @IBOutlet var label: UILabel? override func viewdidload() { super.viewdidload() // Do any required interface initialization here. func didreceive(_ notification: UNNotification) { label?.text = notification.request.content.body

// Minimal Content Extension class NotificationViewController: UIViewController, UNNotificationContentExtension { @IBOutlet var label: UILabel? override func viewdidload() { super.viewdidload() // Do any required interface initialization here. func didreceive(_ notification: UNNotification) { label?.text = notification.request.content.body

// Minimal Content Extension class NotificationViewController: UIViewController, UNNotificationContentExtension { @IBOutlet var label: UILabel? override func viewdidload() { super.viewdidload() // Do any required interface initialization here. func didreceive(_ notification: UNNotification) { label?.text = notification.request.content.body

// Extension Info.plist <plist version="1.0"> <dict> //... <key>nsextension</key> <dict> <key>nsextensionattributes</key> <dict> <key>unnotificationextensioncategory</key> <string>event-invite</string> </dict> //... </dict> </dict> </plist>

// Extension Info.plist <plist version="1.0"> <dict> //... <key>nsextension</key> <dict> <key>nsextensionattributes</key> <dict> <key>unnotificationextensioncategory</key> <string>event-invite</string> </dict> //... </dict> </dict> </plist>

// Extension Info.plist <plist version="1.0"> <dict> //... <key>nsextension</key> <dict> <key>nsextensionattributes</key> <dict> <key>unnotificationextensioncategory</key> <array> <string>event-invite</string> <string>event-changed</string> </array> </dict> //... </dict> </dict> </plist>

Custom Views

// Notification Content Extension class NotificationViewController: UIViewController, UNNotificationContentExtension { @IBOutlet var eventtitle: UILabel! @IBOutlet var eventdate: UILabel! @IBOutlet var eventlocation: UILabel! @IBOutlet var eventmessage: UILabel! func didreceive(_ notification: UNNotification) { let content = notification.request.content eventtitle.text = content.title eventdate.text = content.subtitle eventmessage.text = content.body if let location = content.userinfo["location"] as? String { eventlocation.text = location

// Notification Content Extension class NotificationViewController: UIViewController, UNNotificationContentExtension { @IBOutlet var eventtitle: UILabel! @IBOutlet var eventdate: UILabel! @IBOutlet var eventlocation: UILabel! @IBOutlet var eventmessage: UILabel! func didreceive(_ notification: UNNotification) { let content = notification.request.content eventtitle.text = content.title eventdate.text = content.subtitle eventmessage.text = content.body if let location = content.userinfo["location"] as? String { eventlocation.text = location

// Notification Content Extension class NotificationViewController: UIViewController, UNNotificationContentExtension { @IBOutlet var eventtitle: UILabel! @IBOutlet var eventdate: UILabel! @IBOutlet var eventlocation: UILabel! @IBOutlet var eventmessage: UILabel! func didreceive(_ notification: UNNotification) { let content = notification.request.content eventtitle.text = content.title eventdate.text = content.subtitle eventmessage.text = content.body if let location = content.userinfo["location"] as? String { eventlocation.text = location

// Notification Content Extension class NotificationViewController: UIViewController, UNNotificationContentExtension { @IBOutlet var eventtitle: UILabel! @IBOutlet var eventdate: UILabel! @IBOutlet var eventlocation: UILabel! @IBOutlet var eventmessage: UILabel! func didreceive(_ notification: UNNotification) { let content = notification.request.content eventtitle.text = content.title eventdate.text = content.subtitle eventmessage.text = content.body if let location = content.userinfo["location"] as? String { eventlocation.text = location

// Notification Content Extension class NotificationViewController: UIViewController, UNNotificationContentExtension { @IBOutlet var eventtitle: UILabel! @IBOutlet var eventdate: UILabel! @IBOutlet var eventlocation: UILabel! @IBOutlet var eventmessage: UILabel! func didreceive(_ notification: UNNotification) { let content = notification.request.content eventtitle.text = content.title eventdate.text = content.subtitle eventmessage.text = content.body if let location = content.userinfo["location"] as? String { eventlocation.text = location

// Extension Info.plist <key>nsextensionattributes</key> <dict> <key>unnotificationextensioncategory</key> <string>event-invite</string> <key>unnotificationextensiondefaultcontenthidden</key> <true/> </dict>

// Extension Info.plist <key>nsextensionattributes</key> <dict> <key>unnotificationextensioncategory</key> <string>event-invite</string> <key>unnotificationextensiondefaultcontenthidden</key> <true/> </dict>

// Notification Content Extension class NotificationViewController: UIViewController, UNNotificationContentExtension { override func viewdidload() { super.viewdidload() let size = view.bounds.size preferredcontentsize = CGSize(width: size.width, height: size.width / 2) func didreceive(_ notification: UNNotification) { //...

// Notification Content Extension class NotificationViewController: UIViewController, UNNotificationContentExtension { override func viewdidload() { super.viewdidload() let size = view.bounds.size preferredcontentsize = CGSize(width: size.width, height: size.width / 2) func didreceive(_ notification: UNNotification) { //...

// Extension Info.plist <key>nsextensionattributes</key> <dict> <key>unnotificationextensioncategory</key> <string>event-invite</string> <key>unnotificationextensiondefaultcontenthidden</key> <true/> <key>unnotificationextensioninitialcontentsizeratio</key> <real>0.5</real> </dict>

// Extension Info.plist <key>nsextensionattributes</key> <dict> <key>unnotificationextensioncategory</key> <string>event-invite</string> <key>unnotificationextensiondefaultcontenthidden</key> <true/> <key>unnotificationextensioninitialcontentsizeratio</key> <real>0.5</real> </dict>

Custom Notification UI

Custom Notification UI Presentation size UNNotificationExtensionInitialContentSizeRatio

Custom Notification UI Presentation size UNNotificationExtensionInitialContentSizeRatio Default content UNNotificationExtensionDefaultContentHidden

Custom Notification UI Presentation size UNNotificationExtensionInitialContentSizeRatio Default content UNNotificationExtensionDefaultContentHidden

Media Attachments

// Notification Content Extension Attachments class NotificationViewController: UIViewController, UNNotificationContentExtension { @IBOutlet var eventimage: UIImageView! func didreceive(_ notification: UNNotification) { let content = notification.request.content if let attachment = content.attachments.first { if attachment.url.startaccessingsecurityscopedresource() { eventimage.image = UIImage(contentsOfFile: attachment.url.path!) attachment.url.stopaccessingsecurityscopedresource()

// Notification Content Extension Attachments class NotificationViewController: UIViewController, UNNotificationContentExtension { @IBOutlet var eventimage: UIImageView! func didreceive(_ notification: UNNotification) { let content = notification.request.content if let attachment = content.attachments.first { if attachment.url.startaccessingsecurityscopedresource() { eventimage.image = UIImage(contentsOfFile: attachment.url.path!) attachment.url.stopaccessingsecurityscopedresource()

// Notification Content Extension Attachments class NotificationViewController: UIViewController, UNNotificationContentExtension { @IBOutlet var eventimage: UIImageView! func didreceive(_ notification: UNNotification) { let content = notification.request.content if let attachment = content.attachments.first { if attachment.url.startaccessingsecurityscopedresource() { eventimage.image = UIImage(contentsOfFile: attachment.url.path!) attachment.url.stopaccessingsecurityscopedresource()

// Notification Content Extension Attachments class NotificationViewController: UIViewController, UNNotificationContentExtension { @IBOutlet var eventimage: UIImageView! func didreceive(_ notification: UNNotification) { let content = notification.request.content if let attachment = content.attachments.first { if attachment.url.startaccessingsecurityscopedresource() { eventimage.image = UIImage(contentsOfFile: attachment.url.path!) attachment.url.stopaccessingsecurityscopedresource()

Actions

Default Action Handling

Default Action Handling Delivered to the app Notification gets dismissed immediately

Intercepting Action Response

Intercepting Action Response Delivered to the extension Can delay dismissal

// Intercepting notification action response class NotificationViewController: UIViewController, UNNotificationContentExtension { func didreceive(_ response: UNNotificationResponse, completionhandler done: (UNNotificationContentExtensionResponseOption) -> Void) { server.posteventresponse(response.actionidentifier) { if response.actionidentifier == "accept" { eventresponse.text = "Going!" eventresponse.textcolor = UIColor.green() else if response.actionidentifier == "decline" { eventresponse.text = "Not going :(" eventresponse.textcolor = UIColor.red() done(.dismiss)

// Intercepting notification action response class NotificationViewController: UIViewController, UNNotificationContentExtension { func didreceive(_ response: UNNotificationResponse, completionhandler done: (UNNotificationContentExtensionResponseOption) -> Void) { server.posteventresponse(response.actionidentifier) { if response.actionidentifier == "accept" { eventresponse.text = "Going!" eventresponse.textcolor = UIColor.green() else if response.actionidentifier == "decline" { eventresponse.text = "Not going :(" eventresponse.textcolor = UIColor.red() done(.dismiss)

// Intercepting notification action response class NotificationViewController: UIViewController, UNNotificationContentExtension { func didreceive(_ response: UNNotificationResponse, completionhandler done: (UNNotificationContentExtensionResponseOption) -> Void) { server.posteventresponse(response.actionidentifier) { if response.actionidentifier == "accept" { eventresponse.text = "Going!" eventresponse.textcolor = UIColor.green() else if response.actionidentifier == "decline" { eventresponse.text = "Not going :(" eventresponse.textcolor = UIColor.red() done(.dismiss)

// Intercepting notification action response class NotificationViewController: UIViewController, UNNotificationContentExtension { func didreceive(_ response: UNNotificationResponse, completionhandler done: (UNNotificationContentExtensionResponseOption) -> Void) { server.posteventresponse(response.actionidentifier) { if response.actionidentifier == "accept" { eventresponse.text = "Going!" eventresponse.textcolor = UIColor.green() else if response.actionidentifier == "decline" { eventresponse.text = "Not going :(" eventresponse.textcolor = UIColor.red() done(.dismiss)

// Intercepting notification action response class NotificationViewController: UIViewController, UNNotificationContentExtension { func didreceive(_ response: UNNotificationResponse, completionhandler done: (UNNotificationContentExtensionResponseOption) -> Void) { server.posteventresponse(response.actionidentifier) { if response.actionidentifier == "accept" { eventresponse.text = "Going!" eventresponse.textcolor = UIColor.green() else if response.actionidentifier == "decline" { eventresponse.text = "Not going :(" eventresponse.textcolor = UIColor.red() done(.dismiss)

// Intercepting notification action response class NotificationViewController: UIViewController, UNNotificationContentExtension { func didreceive(_ response: UNNotificationResponse, completionhandler done: (UNNotificationContentExtensionResponseOption) -> Void) { server.posteventresponse(response.actionidentifier) { if response.actionidentifier == "accept" { eventresponse.text = "Going!" eventresponse.textcolor = UIColor.green() else if response.actionidentifier == "decline" { eventresponse.text = "Not going :(" eventresponse.textcolor = UIColor.red() done(.dismissandforwardaction)

Text Input Action

// Text Input Action private func makeeventextensioncategory() -> UNNotificationCategory { let commentaction = UNTextInputNotificationAction( identifier: "comment", title: "Comment", options: [], textinputbuttontitle: "Send", textinputplaceholder: "Type here ") return UNNotificationCategory(identifier: "event-invite", actions: [ acceptaction, declineaction, commentaction ], minimalactions: [ acceptaction, declineaction ], intentidentifiers: [], options: [])

// Text Input Action private func makeeventextensioncategory() -> UNNotificationCategory { let commentaction = UNTextInputNotificationAction( identifier: "comment", title: "Comment", options: [], textinputbuttontitle: "Send", textinputplaceholder: "Type here ") return UNNotificationCategory(identifier: "event-invite", actions: [ acceptaction, declineaction, commentaction ], minimalactions: [ acceptaction, declineaction ], intentidentifiers: [], options: [])

// Text Input Action private func makeeventextensioncategory() -> UNNotificationCategory { let commentaction = UNTextInputNotificationAction( identifier: "comment", title: "Comment", options: [], textinputbuttontitle: "Send", textinputplaceholder: "Type here ") return UNNotificationCategory(identifier: "event-invite", actions: [ acceptaction, declineaction, commentaction ], minimalactions: [ acceptaction, declineaction ], intentidentifiers: [], options: [])

// Text Input Action private func makeeventextensioncategory() -> UNNotificationCategory { let commentaction = UNTextInputNotificationAction( identifier: "comment", title: "Comment", options: [], textinputbuttontitle: "Send", textinputplaceholder: "Type here ") return UNNotificationCategory(identifier: "event-invite", actions: [ acceptaction, declineaction, commentaction ], minimalactions: [ acceptaction, declineaction ], intentidentifiers: [], options: [])

// Text input action response class NotificationViewController: UIViewController, UNNotificationContentExtension { func didreceive(_ response: UNNotificationResponse, completionhandler done: (UNNotificationContentExtensionResponseOption) -> Void) { if let textresponse = response as? UNTextInputNotificationResponse { server.send(textresponse.usertext) { done(.dismiss)

// Text input action response class NotificationViewController: UIViewController, UNNotificationContentExtension { func didreceive(_ response: UNNotificationResponse, completionhandler done: (UNNotificationContentExtensionResponseOption) -> Void) { if let textresponse = response as? UNTextInputNotificationResponse { server.send(textresponse.usertext) { done(.dismiss)

// Text input action response class NotificationViewController: UIViewController, UNNotificationContentExtension { func didreceive(_ response: UNNotificationResponse, completionhandler done: (UNNotificationContentExtensionResponseOption) -> Void) { if let textresponse = response as? UNTextInputNotificationResponse { server.send(textresponse.usertext) { done(.dismiss)

// Text input action response class NotificationViewController: UIViewController, UNNotificationContentExtension { func didreceive(_ response: UNNotificationResponse, completionhandler done: (UNNotificationContentExtensionResponseOption) -> Void) { if let textresponse = response as? UNTextInputNotificationResponse { server.send(textresponse.usertext) { done(.dismiss)

// Text input action response class NotificationViewController: UIViewController, UNNotificationContentExtension { func didreceive(_ response: UNNotificationResponse, completionhandler done: (UNNotificationContentExtensionResponseOption) -> Void) { if let textresponse = response as? UNTextInputNotificationResponse { server.send(textresponse.usertext) { done(.dismiss)

// Custom input accessory view class NotificationViewController: UIViewController, UNNotificationContentExtension { override func canbecomefirstresponder() -> Bool { return true override var inputaccessoryview: UIView { get { return inputview func didreceive(_ response: UNNotificationResponse, completionhandler done: (UNNotificationContentExtensionResponseOption) -> Void) { if response.actionidentifier == "comment" { becomefirstresponder() textfield.becomefirstresponder()

// Custom input accessory view class NotificationViewController: UIViewController, UNNotificationContentExtension { override func canbecomefirstresponder() -> Bool { return true override var inputaccessoryview: UIView { get { return inputview func didreceive(_ response: UNNotificationResponse, completionhandler done: (UNNotificationContentExtensionResponseOption) -> Void) { if response.actionidentifier == "comment" { becomefirstresponder() textfield.becomefirstresponder()

// Custom input accessory view class NotificationViewController: UIViewController, UNNotificationContentExtension { override func canbecomefirstresponder() -> Bool { return true override var inputaccessoryview: UIView { get { return inputview func didreceive(_ response: UNNotificationResponse, completionhandler done: (UNNotificationContentExtensionResponseOption) -> Void) { if response.actionidentifier == "comment" { becomefirstresponder() textfield.becomefirstresponder()

// Custom input accessory view class NotificationViewController: UIViewController, UNNotificationContentExtension { override func canbecomefirstresponder() -> Bool { return true override var inputaccessoryview: UIView { get { return inputview func didreceive(_ response: UNNotificationResponse, completionhandler done: (UNNotificationContentExtensionResponseOption) -> Void) { if response.actionidentifier == "comment" { becomefirstresponder() textfield.becomefirstresponder()

Summary Attachments and custom UI Attachments with service extension Custom UI with content extension Media attachments User interaction

More Information https://developer.apple.com/wwdc16/708

Related Sessions Introduction to Notifications Pacific Heights Wednesday 9:00AM

Labs Notifications Lab Frameworks Lab C Wednesday 11:00AM Notifications Lab Graphics, Games, and Media Lab B Friday 9:00AM