An iOS 10 Local Notification Tutorial
Previous | Table of Contents | Next |
A iOS 10 Sprite Kit Collision Handling Tutorial | An iOS 10 Local Notification Tutorial |
Learn SwiftUI and take your iOS Development to the Next Level |
Notifications provide a mechanism for an application to schedule an alert to notify the user about an event. These notifications take the form of a notification panel containing a message accompanied by a sound and the vibration of the device.
Notifications are categorized as either local or remote. Notifications initiated by apps running on a device are referred to as local notifications. A remote notification, on the other hand, is initiated by a remote server and pushed to the device where it is displayed to the user.
Both local and remote notifications are managed using the classes of the UserNotifications framework in conjunction with the user notification center. In the course of covering the steps to create, send and manage local notifications, this chapter will also outline the various classes provided within UserNotifications framework together with the methods provided by the user notification center.
Creating the Local Notification App Project
The first step in demonstrating the use of local notifications is to create a new Xcode project. Begin by launching Xcode and selecting the options to create a new Swift based Universal project using the Single View Application template. When prompted to do so, name the product NotifyDemo.
Requesting Notification Authorization
Before an app can issue notifications, it must first seek permission to do so from the user. This involves making a call to the user notification center.
The user notification center is responsible for handling, managing and coordinating all of the notifications on a device. In this case, a reference to the current notification center instance needs to be obtained and the requestAuthorization method called on that object.
Edit the ViewController.swift file to import the UserNotifications framework, request authorization and add a variable to store the subtitle of the message, which the user will be able to change from within the notification later in this tutorial:
import UIKit import UserNotifications class ViewController: UIViewController { var messageSubtitle = "Staff Meeting in 20 minutes" override func viewDidLoad() { super.viewDidLoad() UNUserNotificationCenter.current().requestAuthorization(options: [[.alert, .sound, .badge]], completionHandler: { (granted, error) in // Handle Error }) } . . }
Run the app on an iOS device and tap the Allow button when the permission request dialog (Figure 72-1) appears:
Figure 72-1
Designing the User Interface
Select the Main.storyboard file and drag and drop a Button object so that it is positioned in the center of the scene. Using the Auto Layout Resolve Auto Layout Issues menu, select the option to reset to suggested constraints for all of the views in the view controller.
Change the text on the button to read Send Notification, display the Assistant Editor panel and establish an action connection from the button to a method named buttonPressed.
Edit the ViewController.swift file and modify the buttonPressed action method to call a method named sendNotification:
@IBAction func buttonPressed(_ sender: AnyObject) { sendNotification() }
On completion of the layout work, the user interface should match that shown in Figure 72-2 below:
Figure 72-2
Creating the Message Content
The first part of the notification to be created is the message content. The content of the message for a local notification is represented by an instance of the UNMutableNotificationContent class. This class can contain a variety of options including the message title, subtitle and body text. In addition, the message may contain media content such as images and videos. Within the ViewController.swift file, add the sendNotification method as follows:
func sendNotification() { let content = UNMutableNotificationContent() content.title = "Meeting Reminder" content.subtitle = messageSubtitle content.body = "Don't forget to bring coffee." content.badge = 1 }
Note also that the badge property of the content object is set to 1. This configures the notification count that is to appear on the app launch icon on the device after a notification has been triggered as illustrated in Figure 72-3:
Figure 72-3
Specifying a Notification Trigger
Once the content of the message has been created, a trigger needs to be defined that will cause the notification to be presented to the user. Local notifications can be triggered based on elapsed time interval, a specific date and time or a location change. For this example, the notification will be configured to trigger after 5 seconds have elapsed (without repeating).
func sendNotification() { let content = UNMutableNotificationContent() content.title = "Meeting Reminder" content.subtitle = messageSubtitle content.body = "Don't forget to bring coffee." content.badge = 1 let trigger = UNTimeIntervalNotificationTrigger(timeInterval: 5, repeats: false) }
Creating the Notification Request
The next step is to create a notification request object containing the content and trigger objects together with an identifier that can be used to access the notification later if it needs to be modified or deleted. The notification request takes the form of a UNNotificationRequest object, code for which will now need to be added to the sendNotification method:
func sendNotification() { let content = UNMutableNotificationContent() content.title = "Meeting Reminder" content.subtitle = messageSubtitle content.body = "Don't forget to bring coffee." content.badge = 1 let trigger = UNTimeIntervalNotificationTrigger(timeInterval: 5, repeats: false) let requestIdentifier = "demoNotification" let request = UNNotificationRequest(identifier: requestIdentifier, content: content, trigger: trigger) }
Adding the Request
The request object now needs to be added to the notification center where it will be triggered when the specified time has elapsed:
func sendNotification() { let content = UNMutableNotificationContent() content.title = "Meeting Reminder" content.subtitle = messageSubtitle content.body = "Don't forget to bring coffee." content.badge = 1 let trigger = UNTimeIntervalNotificationTrigger(timeInterval: 5, repeats: false) let requestIdentifier = "demoNotification" let request = UNNotificationRequest(identifier: requestIdentifier, content: content, trigger: trigger) UNUserNotificationCenter.current().add(request, withCompletionHandler: { (error) in // Handle error }) }
Testing the Notification
Compile and run the NotifyDemo app on a device or simulator session. Once the app has loaded, tap the Send Notification button and press the Home button to place the app into the background (if using the simulator, select the Hardware -> Home menu option). After 5 seconds have elapsed the notification will appear as shown in Figure 72-4:
Figure 72-4
Open the app once again and tap the button, but do not place the app into the background. This time the notification will not appear. This is the default behavior for user notifications. If the notifications issued by an app are to appear while that app is in the foreground, an additional step is necessary.
Receiving Notifications in the Foreground
As demonstrated in the previous section, when an app that issues a notification is currently in the foreground the notification is not displayed. To change this default behavior, it will be necessary for the view controller to declare itself as conforming to the UNUserNotificationCenterDelegate protocol and implement the userNotification:willPresent method. The current class will also need to be declared as the notification delegate. Remaining within the ViewController.swift file, make these changes as follows:
import UIKit import UserNotifications class ViewController: UIViewController, UNUserNotificationCenterDelegate { . . override func viewDidLoad() { super.viewDidLoad() UNUserNotificationCenter.current().requestAuthorization(options: [[.alert, .sound, .badge]], completionHandler: { (granted, error) in // Handle Error }) UNUserNotificationCenter.current().delegate = self } . . . func userNotificationCenter(_ center: UNUserNotificationCenter, willPresent notification: UNNotification, withCompletionHandler completionHandler: @escaping (UNNotificationPresentationOptions) -> Void) { completionHandler([.alert, .sound]) }
The userNotification:willPresent method simply calls the provided completion handler indicating that the notification should be presented to the user using both the alert message and sound.
Adding Notification Actions
The default action when a notification is tapped by the user is to dismiss the notification and launch the corresponding app. The UserNotifications framework also allows action buttons to be added to notifications. These buttons are displayed when the user presses down with force on the notification message, or swipes the message to the left. For this example, two action buttons will be added to the notification, one of which will instruct the app to repeat the notification while the other will allow the user to input different text to appear in the message subtitle before also repeating the notification.
This will require the creation of two notification action objects as follows:
let repeatAction = UNNotificationAction(identifier:"repeat", title:"Repeat",options:[]) let changeAction = UNTextInputNotificationAction(identifier: "change", title: "Change Message", options: [])
Next, these action objects need to be placed in a notification category object and the category object added to the user notification center after being assigned an identifier:
let category = UNNotificationCategory(identifier: "actionCategory", actions: [repeatAction, changeAction], intentIdentifiers: [], options: []) content.categoryIdentifier = "actionCategory" UNUserNotificationCenter.current().setNotificationCategories([category])
Combining these steps with the existing sendNotification method results in code that reads as follows:
func sendNotification() { let content = UNMutableNotificationContent() content.title = "Meeting Reminder" content.subtitle = messageSubtitle content.body = "Don't forget to bring coffee." content.badge = 1 let repeatAction = UNNotificationAction(identifier:"repeat", title:"Repeat",options:[]) let changeAction = UNTextInputNotificationAction(identifier: "change", title: "Change Message", options: []) let category = UNNotificationCategory(identifier: "actionCategory", actions: [repeatAction, changeAction], intentIdentifiers: [], options: []) content.categoryIdentifier = "actionCategory" UNUserNotificationCenter.current().setNotificationCategories( [category]) . . . }
Compile and run the app on a physical device, trigger the notification and perform a deep press on the message when it appears. The action buttons should appear beneath the message as illustrated in Figure 72-5 below:
Figure 72-5
Tap the Change Message button and note that the keyboard and text input field appear. Although the action buttons are now present, some work still needs to be performed to handle the actions within the view controller.
Handling Notification Actions
When an action is selected by the user, the userNotification:didReceive method of the designated notification delegate is called by the user notification center. Since the ViewController class has already been declared as implementing the UNUserNotificationCenterDelegate protocol and assigned as the delegate, all that needs to be added to the ViewController.swift file is the userNotification:didReceive method:
func userNotificationCenter(_ center: UNUserNotificationCenter, didReceive response: UNNotificationResponse, withCompletionHandler completionHandler: @escaping () -> Void) { switch response.actionIdentifier { case "repeat": self.sendNotification() case "change": let textResponse = response as! UNTextInputNotificationResponse messageSubtitle = textResponse.userText self.sendNotification() default: break } completionHandler() }
The method is passed a UNNotificationResponse object from which we can extract the identifier of the action that triggered the call. A switch statement is then used to identify the action and take appropriate steps. If the repeat action is detected the notification is resent. In the case of the change action, the text entered by the user is obtained from the response object and assigned to the messageSubtitle variable before the notification is sent again.
Compile and run the app once again and verify that the actions perform as expected.
Managing Notifications
In addition to creating notifications, the UserNotifications framework also provides ways to manage notifications, both while they are still pending and after they have been delivered. One or more pending notifications may be removed by passing an array of request identifiers through to the removal method of the user notification center:
UNUserNotificationCenter.current() .removePendingNotificationRequests(withIdentifiers: [demoIdentifer, demoIdentifier2])
Similarly, the content of a pending intent may be updated by creating an updated request object with the same identifier containing the new content and adding it to the notifications center:
UNUserNotificationCenter.current().add(updatedRequest, withCompletionHandler: { (error) in // Handle error })
Finally, previously delivered notifications can be deleted from the user’s notification history by a call to the user notification center passing through one or more request identifiers matching the notifications to be deleted:
UNUserNotificationCenter.current() .removeDeliveredNotifications(withIdentifiers: [demoIdentifier])
Summary
Notifications can be triggered locally by an app or sent remotely via a server. Both forms of notification are managed by the UserNotifications framework. An application that needs to issue local notifications must first seek permission to do so from the user.
A notification consists of a content object, a request object and access to the notifications center. In addition, a notification may also include actions which appear in the form of buttons when a force touch press is performed on the notification message. These actions include the ability for the user to input text to be sent to the app that initiated the intent.
Learn SwiftUI and take your iOS Development to the Next Level |
Previous | Table of Contents | Next |
A iOS 10 Sprite Kit Collision Handling Tutorial | An iOS 10 Local Notification Tutorial |