An Overview of Notifications in watchOS 2
Previous | Table of Contents | Next |
A watchOS 2 WatchKit Map Tutorial | A watchOS 2 WatchKit Notification Tutorial |
Purchase the full edition of this watchOS 2 App Development Essentials book in eBook ($12.99) or Print ($27.99) format watchOS 2 App Development Essentials Print and eBook (ePub/PDF/Kindle) editions contain 35 chapters. |
When an iOS app receives a notification, the operating system will decide whether the user should be notified of this event on the iPhone or the paired Apple Watch device. If, for example, the iPhone is currently locked and the user is wearing and has recently interacted with the Apple Watch, the notification will most likely be delivered to the watch.
Not all iOS apps receive notifications, of course, but for those that do it is important that the companion WatchKit app handle those notifications appropriately.
Default WatchKit Notification Handling
For many WatchKit apps it may not be necessary to make any changes to support notifications. In fact, the only step necessary to provide basic notification support for a WatchKit app is to add appropriately sized notification icons within the AppIcon image set of the WatchKit app bundle.
By default, if a notification arrives for an iOS app with a companion WatchKit app, the system will first decide whether to display the alert on the iPhone or the Apple Watch. In the event that the notification is delivered to the Apple Watch a “short-look” notification scene will first be displayed. This consists of the app icon, the title from the notification and the name of the WatchKit app.
A few seconds after the short-look notification has displayed, the long-look notification panel will appear. By default, this contains a smaller app icon, the name of the app, and the title and alert text from the notification. In addition, a Dismiss button is included which, when tapped, closes the notification and returns the user to the previous activity. Tapping anywhere else on the notification scene launches the WatchKit app associated with the notification. Figure 32-1, for example, shows a typical default long-look notification:
Figure 32-1
All of the default functionality outlined so far is provided without making any code changes to the WatchKit app. It is, however, possible to add additional capabilities to notification handling for the WatchKit app. Perhaps the most common requirement is the addition of notification action buttons.
Creating Notification Actions
Notifications within an iOS app can be configured to add action buttons which appear within the notification panel and, when tapped by the user, trigger application specific actions. If the iOS app has a companion WatchKit app, these same notification action buttons also appear within the long-look notification on the Apple Watch device. Figure 32-2, for example, shows a long-look notification which has been scrolled up to reveal two action buttons in addition to the default “Dismiss” button:
Figure 32-2
Notification actions are configured from within the code of the containing iOS app using a multi-step process. The code to configure the notification actions will need to be executed each time the iOS app runs, so is typically executed in the didFinishLaunchingWithOptions method of the application delegate class.
The first step in adding notification actions is to create a notification action object for each action to be added. Each notification action object is created as an instance of the UIMutableUserNotificationAction class which needs to be customized via a range of available properties:
- identifier – A string which uniquely identifies the action. This identifier will be referenced in the action handler code to ascertain which action was selected by the user.
- title – A string value containing the text that is to appear on the action button within the notification panel.
- destructive – A Boolean value indicating whether selection of the action will result in the loss of user data or input. When set to true, this causes the title string on the button to appear in red.
- authentication – A Boolean value indicating whether or not the user needs to unlock the device before the action can be performed.
- activationMode – Used to indicate whether the action should be performed in the foreground or background. In background mode the containing iOS app is launched in the background to perform the task. When a notification appears on the iPhone device, a foreground mode action causes the iOS app to be launched in the foreground. Selection of a foreground mode action when the notification is delivered to the Apple Watch causes the WatchKit app to be launched.
- behavior – Indicates whether or not the action is required to obtain text input from the user.
The following code demonstrates the creation of two notification actions, one configured for background mode and the other for foreground mode:
var repeatAction = UIMutableUserNotificationAction() repeatAction.identifier = "REPEAT_IDENTIFIER" repeatAction.title = "Repeat" repeatAction.destructive = false repeatAction.authenticationRequired = false repeatAction.activationMode = UIUserNotificationActivationMode.Background var modifyAction = UIMutableUserNotificationAction() modifyAction.identifier = "MODIFY_IDENTIFIER" modifyAction.title = "Modify" modifyAction.destructive = false modifyAction.authenticationRequired = false modifyAction.activationMode = UIUserNotificationActivationMode.Foreground
Once the notification action objects have been created, they need to be packaged into a notification category object in the form of an instance of the UIMutableUserNotificationCategory class. As with the notification actions, the category object must have assigned to it a unique identifier string. The following code creates a new notification category containing the above notification action objects:
var notificationCategory = UIMutableUserNotificationCategory() notificationCategory.identifier = "REMINDER_CATEGORY" notificationCategory.setActions([repeatAction, modifyAction], forContext: UIUserNotificationActionContext.Default)
Finally, the notification category needs to be bundled into a UIUserNotificationSettings object along with any other required settings and registered with the notification system using the registerUserNotificationSettings method of the iOS application’s UIApplication instance:
let settings = UIUserNotificationSettings(forTypes: [UIUserNotificationType.Sound, UIUserNotificationType.Alert, UIUserNotificationType.Badge], categories: [notificationCategory]) application.registerUserNotificationSettings(settings)
Inline Text Replies
A new feature introduced in watchOS 2 and iOS 9 allows the user to input text into a notification and have it delivered to the corresponding app. An action is designated as accepting text input using the behavior property of the UIMutableUserNotificationAction instance as follows:
let replyAction: UIMutableUserNotificationAction = UIMutableUserNotificationAction() replyAction.identifier = "REPLY_IDENTIFIER" replyAction.title = "Reply" replyAction.destructive = false replyAction.authenticationRequired = false replyAction.behavior = UIUserNotificationActionBehavior.TextInput
When text input is provided by the user within the notification it is passed to the corresponding WatchKit app via one of the action handler methods.
When the user selects a text input action within the notification the standard WatchKit text input controller will appear providing the option to make the input using voice dictation, a selection from a range of preset options or emoji selection. Preset text options can be provided by implementing the suggestionsForResponseToActionWithIdentifier method within the notification interface controller class as follows:
override func suggestionsForResponseToActionWithIdentifier(identifier: String, forLocalNotification localNotification: UILocalNotification) -> [NSAttributedString] { let suggestion1 = NSMutableAttributedString(string: "I’m too busy") let suggestion2 = NSMutableAttributedString(string: "I’m on my way") let suggestions = [suggestion1, suggestion2] return suggestions }
Handling Standard Notification Actions
Notifications are categorized as being either local or remote. A local notification is typically initiated from within the containing iOS app. A remote notification, on the other hand, is sent over the internet to the iPhone from a remote server.
As previously outlined, a notification can appear either on the iPhone device or the paired Apple Watch. When a notification action on an Apple Watch is selected by the user, the handler method that gets called will depend on whether the notification was remote or local in origin and whether the notification action was configured for background or foreground mode.
Purchase the full edition of this watchOS 2 App Development Essentials book in eBook ($12.99) or Print ($27.99) format watchOS 2 App Development Essentials Print and eBook (ePub/PDF/Kindle) editions contain 35 chapters. |
application:handleActionWithIdentifier:forRemoteNotification:completionHandler:
If the notification is local, however, the following method will be called on the app delegate of the containing iOS app when a background action is selected:
application:handleActionWithIdentifier:forLocalNotification:completionHandler:
When a remote notification appears on the Apple Watch and the user selects a foreground notification action, the WatchKit app will launch and the following method on the extension delegate will be called:
handleActionWithIdentifier:forRemoteNotification:
The same scenario involving a local notification on the Apple Watch will result in the following method being called on the extension delegate of the WatchKit app:
handleActionWithIdentifier:forLocalNotification:
Handling Inline Text Reply Actions
Local notification inline text reply actions trigger the following method on the extension delegate of the WatchKit app:
handleActionWithIdentifier:forLocalNotification:withResponseInfo:
In the event that the notification containing the inline text reply action was remotely initiated, the following method of the extension delegate will be called:
handleActionWithIdentifier:forRemoteNotification:withResponseInfo:
Both methods are passed a string containing the notification category identifier, the notification object and dictionary object containing the text entered by the user. The key to access to the text within the dictionary is UIUserNotificationActionResponseTypedTextKey. The following code, for example, shows an example implementation of the handleActionWithIdentifier:forLocalNotification:withResponseInfo: method in which the user’s text input is extracted from the dictionary and printed to the console:
func handleActionWithIdentifier(identifier: String, forLocalNotification localNotification: UILocalNotification, withResponseInfo responseInfo: [NSObject : AnyObject]) { let reply = responseInfo[UIUserNotificationActionResponseTypedTextKey] print(reply) }
The topics of WatchKit notification handling, action notifications and inline text input will be covered in further detail in the next chapters (A watchOS 2 WatchKit Notification Tutorial, A watchOS 2 WatchKit Custom Notification Tutorial and A watchOS 2 WatchKit Inline Notification Text Reply Tutorial).
Responding to Notifications
When a notification arrives on the Apple Watch, the WatchKit app will be notified via method call. The specific method that is called depends on whether notification is local or remote in origin and whether or not the WatchKit app is currently active.
When the WatchKit app is active when the notification arrives, either the didReceiveRemoteNotification or the didReceiveLocalNotification method of the extension delegate will be called, depending on whether the notification was initiated remotely or locally. These methods are then able to make changes where necessary within the running app in response to the notification.
If the WatchKit app is inactive when the notification is triggered, either the didReceiveRemoteNotification:withCompletion: or the didReceiveLocalNotification:withCompletion: method of the notification interface controller will be called before the notification interface is displayed to the user. When working with custom notifications, these methods will need to update the custom notification scene before calling the supplied completion handler.
Custom Notifications
The previously outlined default notification handling within WatchKit is somewhat limited in terms of customization options. While it is possible to add action buttons to the notification when it is displayed to the user, there is no control of the layout and content that is presented within the notification scene. This shortcoming can be overcome, however, through the use of custom notifications.
Custom notifications allow the appearance of a notification category on the Apple Watch to be designed in terms of the interface objects that are presented to the user and the content that is displayed on those objects. In fact, a dynamic custom interface can contain any combination of non-interactive interface objects such as Label, Map and Image objects.
A custom notification is made up of two parts referred to as static and dynamic notifications.
Dynamic and Static Notifications
Custom notifications consist of a static and a dynamic notification. The static notification consists of a Label object which displays the content of the notification’s alert body text. The static notification scene can be customized by adding additional non-interactive interface objects such as Labels and Images (note that any images displayed on the static notification scene must be bundled with the WatchKit app and not the extension), and the attributes of those objects can be customized at design time. Once those attributes have been set, however, there is no way to change the appearance or content displayed on the objects before the static notification appears (hence the term static).
An optional dynamic notification may also be added to the static notification. The dynamic notification scene may also be customized in terms of layout and the addition of non-interactive interface objects. The difference with the dynamic notification scene is that it has associated with it a notification interface controller (subclassed from WKUserNotificationInterfaceController).
As with a standard interface controller class, the notification interface controller can contain outlets connected to interface objects in the dynamic notification scene. When a notification arrives on the Apple Watch device, the dynamic notification interface controller is launched and passed via a handler method a notification object containing details of the alert.
The notification controller handler method is then given the opportunity to update the dynamic notification scene via outlet connections based on the details of the alert before it is presented to the user.
The decision at runtime as to whether the static or dynamic notification is used to deliver a notification on the Apple Watch is made by watchOS based on a number of factors including the resources available on the watch device and the amount of time it takes the dynamic notification handler method to prepare the scene for display.
Adding a Custom Notification to a WatchKit App
A custom notification can be added to a WatchKit app at creation time by enabling the Include Notification Scene option in the new target options panel as highlighted in Figure 32-3:
Figure 32-3
Alternatively, a custom notification may be added to an existing project using the following steps:
1. Drag and drop a Notification Interface Controller object from the Object Library onto the WatchKit App storyboard canvas.
2. Ctrl-click on the WatchKit Extension folder in the Project Navigator panel, select New File… and add a new Cocoa Touch Class to the project subclassed from WKUserNotificationInterfaceController.
3. Select the Static Interface scene within the storyboard, display the Attributes Inspector panel and enable the Has Dynamic Interface option. This will add the Dynamic Interface scene to the storyboard.
4. Select the newly added Dynamic Interface scene, display the Identity Inspector and change the Class menu to the class added in step 2 above.
Once a custom notification has been added with dynamic support, the scenes will appear in the storyboard as illustrated in Figure 32-4:
Figure 32-4
Configuring the Notification Category
As previously discussed, notifications have an associated category identifier that is used to differentiate one notification type from another within an app. Custom notifications also have a category identifier which can be specified from within the Document Outline panel. To access and modify the category identifier for a custom notification, select the static notification scene and display the Document Outline panel. Within the Document Outline panel, unfold the Static Notification Interface Controller section, select the Notification Category entry and, within the Attributes Inspector, change the Name field to the new identifier string:
Figure 32-5
Once the custom notification has been assigned a category identifier, that identifier will need to be referenced whenever notification events are configured if those notifications are to be displayed using the custom notification.
Updating the Dynamic Notification Scene
In order for the notification interface controller to be able to dynamically update the interface objects in the dynamic scene, those objects must be connected to outlets. Once those outlets are configured, the code to update the interface needs to be placed in a handler method within the notification interface controller class. By default, Xcode will have placed templates for these methods within the notification interface controller class file. The choice of handler method to use depends on whether the notification is local or remote. For remote notifications the didReceiveRemoteNotification:withCompletion method of the notification controller is called by the system while local notifications result in a call to the didReceiveLocalNotification:withCompletion handler method.
Each method is passed a notification object from which can be obtained the details of the alert. For local notifications this takes the form of a UILocalNotification object. Remote notifications, on the other hand, receive a Dictionary object containing key-value pairs as defined by the remote notification server.
The handler methods are also passed a reference to a completion handler which must be called once the user interface updates are complete. If the completion handler is not called, or the user interface update takes too long to complete, the system will revert to the static notification.
The topic of custom notifications will be covered in further detail in the chapter entitled A WatchKit Custom Notification Tutorial.
Summary
Notifications are a common feature of many iOS applications and are often delivered to the paired Apple Watch, especially if the iPhone device is locked. A considerable amount of notification support is provided by default for WatchKit apps, including the appearance of both short and long-look notification scenes. Notifications can also be extended to include action buttons which can be configured to perform application specific tasks when selected by the user.
Custom notifications may also be used to provide a greater level of control over the layout and content of notifications when delivered to the Apple Watch device.
Purchase the full edition of this watchOS 2 App Development Essentials book in eBook ($12.99) or Print ($27.99) format watchOS 2 App Development Essentials Print and eBook (ePub/PDF/Kindle) editions contain 35 chapters. |
Previous | Table of Contents | Next |
A watchOS 2 WatchKit Map Tutorial | A watchOS 2 WatchKit Notification Tutorial |