Documentation Archive

Developer

Local and Remote Notification Programming Guide

On This Page

Scheduling and Handling Local Notifications

Local notifications give you a way to alert the user at times when your app might not be running. You schedule local notifications at a time when your app is running either in the foreground or background. After scheduling a notification, the system takes on the responsibility of delivering the notification to the user at the appropriate time. Your app does not need to be running for the system to deliver the notification.

If your app is not running, or if it is in the background, the system displays local notifications directly to the user. The system can alert the user with an alert panel or banner, with a sound, or by badging your app’s icon. If your app provides a notification content app extension, the system can even use your custom interface to alert the user. If your app is in the foreground when a notification arrives, the system gives your app the opportunity to handle the notification internally.

Configuring a Local Notification

The steps for configuring a local notification are as follows:

  1. Create and configure a UNMutableNotificationContent object with the notification details.

  2. Create a UNCalendarNotificationTrigger, UNTimeIntervalNotificationTrigger, or UNLocationNotificationTrigger object to describe the conditions under which the notification is delivered.

  3. Create a UNNotificationRequest object with the content and trigger information.

  4. Call the addNotificationRequest:withCompletionHandler: method to schedule the notification; see Scheduling Local Notifications for Delivery

When creating the content for a notification, fill in the properties of the UNMutableNotificationContent object that reflect the type of interaction you want with the user. For example, fill in the title and body properties when you want to display an alert. The system uses the information you provide to determine how to interact with the user. You can also use the data in this object when handling a local notification that has been delivered to your app.

After creating the notification content, create a trigger object that defines when to deliver the notification. The User Notifications framework provides both time-based and location-based triggers. Configure the trigger with the required conditions and use that object plus your content to create the UNNotificationRequest object.

Listing 3-1 shows how to create and configure a local notification related to an alarm. The use of a UNCalendarNotificationTrigger causes the notification to be delivered at a specific date or time, which in this example is the next time the clock reaches 7:00 in the morning.

Listing 3-1Creating and configuring a local notification

Objective-C

  1. UNMutableNotificationContent* content = [[UNMutableNotificationContent alloc] init];
  2. content.title = [NSString localizedUserNotificationStringForKey:@"Wake up!" arguments:nil];
  3. content.body = [NSString localizedUserNotificationStringForKey:@"Rise and shine! It's morning time!"
  4. arguments:nil];
  5. // Configure the trigger for a 7am wakeup.
  6. NSDateComponents* date = [[NSDateComponents alloc] init];
  7. date.hour = 7;
  8. date.minute = 0;
  9. UNCalendarNotificationTrigger* trigger = [UNCalendarNotificationTrigger
  10. triggerWithDateMatchingComponents:date repeats:NO];
  11. // Create the request object.
  12. UNNotificationRequest* request = [UNNotificationRequest
  13. requestWithIdentifier:@"MorningAlarm" content:content trigger:trigger];

Swift

  1. let content = UNMutableNotificationContent()
  2. content.title = NSString.localizedUserNotificationString(forKey: "Wake up!", arguments: nil)
  3. content.body = NSString.localizedUserNotificationString(forKey: "Rise and shine! It's morning time!",
  4. arguments: nil)
  5. // Configure the trigger for a 7am wakeup.
  6. var dateInfo = DateComponents()
  7. dateInfo.hour = 7
  8. dateInfo.minute = 0
  9. let trigger = UNCalendarNotificationTrigger(dateMatching: dateInfo, repeats: false)
  10. // Create the request object.
  11. let request = UNNotificationRequest(identifier: "MorningAlarm", content: content, trigger: trigger)

Providing an identifier for the UNNotificationRequest object gives you a way to identify local notifications after they have been scheduled. You can use identifiers to look up pending requests later and to cancel them before they are delivered. For more information on scheduling and canceling requests, see Scheduling Local Notifications for Delivery.

Assigning Custom Actions to a Local Notification

To display custom actions in the interface for a local notification, assign one of your registered category identifiers to the categoryIdentifier property of your UNMutableNotificationContent object during configuration. The system uses the category information to determine which action buttons, if any, to include in the notification interface. You must assign a value to this property before scheduling the notification request.

Listing 3-2 shows how to specify the category identifier for a local notification. In this example, the “TIMER_EXPIRED” string represents a category that was defined at launch time and that includes two custom actions. The code for registering this category is shown in Listing 2-3.

Listing 3-2Defining a category of actions for a local notification

Objective-C

  1. UNNotificationContent *content = [[UNNotificationContent alloc] init];
  2. // Configure the content. . .
  3. // Assign the category (and the associated actions).
  4. content.categoryIdentifier = @"TIMER_EXPIRED";
  5. // Create the request and schedule the notification.

Swift

  1. let content = UNMutableNotificationContent()
  2. // Configure the content. . .
  3. // Assign the category (and the associated actions).
  4. content.categoryIdentifier = "TIMER_EXPIRED"
  5. // Create the request and schedule the notification.

For information on how to register custom actions with a category, see Configuring Categories and Actionable Notifications

Adding a Sound to the Notification Content

If you want a local notification to play a sound when it is delivered, assign a value to the sound property of your UNMutableNotificationContent object. You specify sounds using a UNNotificationSound object, which lets you play either a custom sound or the default notification sound. Custom sounds must reside locally on the user’s device before they can be played. Store the sound files for your notifications in your app’s main bundle or download them and store them in the Library/Sounds subdirectory of your app’s container directory.

To play the default sound, create the sound file and assign it to your notification content. For example:

Objective-C

  1. content.sound = [UNNotificationSound defaultSound];

Swift

  1. content.sound = UNNotificationSound.default()

When specifying custom sounds, specify only the filename of the sound file that you want played. If the system finds a suitable sound file with the name you provided, it plays that sound when delivering the notification. If the system does not find a suitable sound file, it plays the default sound.

Objective-C

  1. content.sound = [UNNotificationSound soundNamed:@"MySound.aiff"];

Swift

  1. content.sound = UNNotificationSound(named: "MySound.aiff")

For information about the supported sound file formats, see UNNotificationSound Class Reference.

Scheduling Local Notifications for Delivery

To schedule a local notification for delivery, create your UNNotificationRequest object and call the addNotificationRequest:withCompletionHandler: method of UNUserNotificationCenter. The system schedules local notifications asynchronously, calling your completion handler block when scheduling is complete or when an error occurs. Listing 3-3 shows how to schedule a local notification for delivery. The code in this example completes the scheduling of the notification created in Listing 3-1.

Listing 3-3Scheduling a local notification for delivery

Objective-C

  1. // Create the request object.
  2. UNNotificationRequest* request = [UNNotificationRequest
  3. requestWithIdentifier:@"MorningAlarm" content:content trigger:trigger];
  4. UNUserNotificationCenter* center = [UNUserNotificationCenter currentNotificationCenter];
  5. [center addNotificationRequest:request withCompletionHandler:^(NSError * _Nullable error) {
  6. if (error != nil) {
  7. NSLog(@"%@", error.localizedDescription);
  8. }
  9. }];

Swift

  1. // Create the request object.
  2. let request = UNNotificationRequest(identifier: "MorningAlarm", content: content, trigger: trigger)
  3. // Schedule the request.
  4. let center = UNUserNotificationCenter.current()
  5. center.add(request) { (error : Error?) in
  6. if let theError = error {
  7. print(theError.localizedDescription)
  8. }
  9. }

Scheduled local notifications remain active until they are unscheduled by the system or until you cancel them explicitly. The system unschedules notifications automatically after they are delivered, unless the notification’s trigger is configured to repeat. To cancel an individual notification before it is delivered, or to cancel a repeating notification, call the removePendingNotificationRequestsWithIdentifiers: method of UNUserNotificationCenter. The notification being canceled must have an identifier assigned to its UNNotificationRequest object. To cancel all pending local notifications, regardless of whether they have a request identifier, call the removeAllPendingNotificationRequests method instead.

Responding to the Delivery of Notifications

When your app is not running or is in the background, the system automatically delivers local and remote notifications using the interactions you specified. If the user selects an action, or chooses one of the standard interactions, the system notifies your app of the user’s selection. Your code can then use that selection to perform additional tasks. If your app is running in the foreground, notifications are delivered directly to your app. You can then decide whether to handle the notification quietly or alert the user.

To respond to the delivery of notifications, you must implement a delegate for the shared UNUserNotificationCenter object. Your delegate object must conform to the UNUserNotificationCenterDelegate protocol, which the notification center uses to deliver notification information to your app. A delegate is required if your notifications contain custom actions.

For additional information on how to implement your delegate object, see UNUserNotificationCenterDelegate Protocol Reference.

Handling Notifications When Your App Is in the Foreground

If a notification arrives while your app is in the foreground, you can silence that notification or tell the system to continue to display the notification interface. The system silences notifications for foreground apps by default, delivering the notification’s data directly to your app. You can use the notification data to update your app’s interface directly. For example, if a new sports score arrived, you would just update that information in your interface.

If you want the system to continue to display the notification interface, provide a delegate object for the UNUserNotificationCenter and implement the userNotificationCenter:willPresentNotification:withCompletionHandler: method. Your implementation of this method should still process the notification data. When finished, execute the provided completion handler block with the delivery option (if any) that you want the system to use. If you do not specify any options, the system silences the notification. Listing 3-4 shows a sample implementation of this method that tells the system to play a sound. The notification’s payload identifies which sound to play.

Listing 3-4Playing a sound while your app is in the foreground

Objective-C

  1. - (void)userNotificationCenter:(UNUserNotificationCenter *)center
  2. willPresentNotification:(UNNotification *)notification
  3. withCompletionHandler:(void (^)(UNNotificationPresentationOptions options))completionHandler {
  4. // Update the app interface directly.
  5. // Play a sound.
  6. completionHandler(UNNotificationPresentationOptionSound);
  7. }

Swift

  1. func userNotificationCenter(_ center: UNUserNotificationCenter,
  2. willPresent notification: UNNotification,
  3. withCompletionHandler completionHandler: @escaping (UNNotificationPresentationOptions) -> Void) {
  4. // Update the app interface directly.
  5. // Play a sound.
  6. completionHandler(UNNotificationPresentationOptions.sound)
  7. }

The system does not call the userNotificationCenter:willPresentNotification:withCompletionHandler: method when your app is in the background or is not running. In those cases, the system alerts the user according to the information in the notification itself. You can still determine whether a notification was delivered using the getDeliveredNotificationsWithCompletionHandler: method of the UNUserNotificationCenter object.

Responding to the Selection of a Custom Action

When the user selects a custom action from the notification interface, the system notifies your app of the user’s choice. Responses to custom actions are packaged in a UNNotificationResponse object and delivered to the delegate of your app’s shared UNUserNotificationCenter object. To receive responses, your delegate object must implement the userNotificationCenter:didReceiveNotificationResponse:withCompletionHandler: method. Your implementation of that method must be able to process all of the custom actions supported by your app or app extension.

If your app or app extension is not running when a response is received, the system launches your app or app extension in the background to process the response. Use the provided background time to update your data structures and your app’s interface to reflect the user’s choice. Do not use the time to perform tasks unrelated to the processing of the custom action.

Listing 3-5 shows an implementation of the response handler method for a timer app with multiple categories and custom actions. The implementation uses both the action and the categoryIdentifier property to determine an appropriate course of action.

Listing 3-5Handling a custom notification action

Objective-C

  1. - (void)userNotificationCenter:(UNUserNotificationCenter *)center
  2. didReceiveNotificationResponse:(UNNotificationResponse *)response
  3. withCompletionHandler:(void (^)(void))completionHandler {
  4. if ([response.notification.request.content.categoryIdentifier isEqualToString:@"TIMER_EXPIRED"]) {
  5. // Handle the actions for the expired timer.
  6. if ([response.actionIdentifier isEqualToString:@"SNOOZE_ACTION"])
  7. {
  8. // Invalidate the old timer and create a new one. . .
  9. }
  10. else if ([response.actionIdentifier isEqualToString:@"STOP_ACTION"])
  11. {
  12. // Invalidate the timer. . .
  13. }
  14. }
  15. // Else handle actions for other notification types. . .
  16. }

Swift

  1. func userNotificationCenter(_ center: UNUserNotificationCenter,
  2. didReceive response: UNNotificationResponse,
  3. withCompletionHandler completionHandler: @escaping () -> Void) {
  4. if response.notification.request.content.categoryIdentifier == "TIMER_EXPIRED" {
  5. // Handle the actions for the expired timer.
  6. if response.actionIdentifier == "SNOOZE_ACTION" {
  7. // Invalidate the old timer and create a new one. . .
  8. }
  9. else if response.actionIdentifier == "STOP_ACTION" {
  10. // Invalidate the timer. . .
  11. }
  12. }
  13. // Else handle actions for other notification types. . .
  14. }

Handling the Standard System Actions

In the system’s notification interface, users can explicitly dismiss the notification interface or launch your app instead of selecting one of your custom actions. Dismissing the interface involves tapping an applicable button or closing the interface directly; ignoring a notification or flicking a notification banner away does not represent an explicit dismissal. When system actions are triggered, the user notification center reports them to the userNotificationCenter:didReceiveNotificationResponse:withCompletionHandler: method its delegate. The response object passed to that method contains one of the following action identifiers:

You handle the standard system actions in the same way that you handle other actions. Listing 3-6 shows a template for the userNotificationCenter:didReceiveNotificationResponse:withCompletionHandler: method that checks for these special actions.

Listing 3-6Handling the standard system actions

Objective-C

  1. - (void)userNotificationCenter:(UNUserNotificationCenter *)center
  2. didReceiveNotificationResponse:(UNNotificationResponse *)response
  3. withCompletionHandler:(void (^)(void))completionHandler {
  4. if ([response.actionIdentifier isEqualToString:UNNotificationDismissActionIdentifier]) {
  5. // The user dismissed the notification without taking action.
  6. }
  7. else if ([response.actionIdentifier isEqualToString:UNNotificationDefaultActionIdentifier]) {
  8. // The user launched the app.
  9. }
  10. // Else handle any custom actions. . .
  11. }

Swift

  1. func userNotificationCenter(_ center: UNUserNotificationCenter,
  2. didReceive response: UNNotificationResponse,
  3. withCompletionHandler completionHandler: @escaping () -> Void) {
  4. if response.actionIdentifier == UNNotificationDismissActionIdentifier {
  5. // The user dismissed the notification without taking action
  6. }
  7. else if response.actionIdentifier == UNNotificationDefaultActionIdentifier {
  8. // The user launched the app
  9. }
  10. // Else handle any custom actions. . .
  11. }