Creating and Scheduling Local Notifications with async/await

Creating and Scheduling Local Notifications with async/await

By the end of this tutorial, you will be able to schedule local user notifications in your iOS application using the UserNotifications framework.

Once you have the authorization to send notifications, as explored on Requesting User Authorization for Notifications with async/await, it is time to create and schedule notifications using the user notification center.

In this tutorial, we will learn how to create a user notification, from the content to scheduling it with a time-based trigger. Let's go.

Creating Notifications

When creating a notification you will have to set up the content of the notification and define which type of event and conditions will trigger it.

First, create a constant of the type UNMutableNotificationContent. It is an object with editable content for your notification. With it, you can set basic attributes of notification, like:

  • title: the reason for the notification being shown (e.g. "It is coffee time!")
  • subtitle: a secondary description of the reason the notification was shown (e.g. "Every day at 10:00 is time to a break.")
  • body: the message that is displayed in the notification alert (e.g. "Our favorite café in Naples is the Napoli Café. Try the cappuccino!")
  • sound: a sound that plays when the notification is delivered

In the documentation for the class UNMutableNotificationContent, you can find many other attributes you can set at the notification content.

Now, let's create a notification for an application that reminds you every day at a specific time that it is "coffee time".

// 1. Create a new mutable notification content object
let notificationContent = UNMutableNotificationContent()

// 2. Set up the title and subtitle of the notification
notificationContent.title = "It is coffee time!"
notificationContent.subtitle = "Everyday at 10:00 is time to a break."

// 3. Set up the body of the notification
notificationContent.body = "Our favorite café in Naples is the Napoli Café. Try the cappuccino!"

Now that we have the content of the notification set up we need to tell the notification center what type of event will trigger the notification. You can set up a local notification to be triggered by:

We are going to create a calendar trigger that will deliver the notification on a specific date and time. To create a notification that is triggered every morning at 10:00 we must create a DateComponents object and set the hour and minute properties. This object will then be used to create the notification trigger.

// 4. Create the Date Components object
var dateComponents = DateComponents()

// 5. Set up the calendar type
dateComponents.calendar = Calendar.current

// 6. Set up the hours and minutes for the notification to be delivered
dateComponents.hour = 10  
dateComponents.minute = 00

You can set up other properties of the Date Components object if you want to create a more specific calendar trigger, like the weekday property. You can see more details about the DateComponents structure on its documentation page

Once you set up the time the notification will be delivered, create an UNCalendarNotificationTrigger object using the dateComponents we have just created. Since we want our notification to be delivered every day at 10:00 set the repeats parameter to true.

// 7. Create the trigger as a repeating event.
let calendarTrigger = UNCalendarNotificationTrigger(
         dateMatching: dateComponents, repeats: true)

With the trigger in our hands, we are almost done. Before being able to create the notification request object that will be used to schedule the notification in the notification center we must create an identifier for our notification. The identifier of a notification request is always a String.

// 8. Create an identifier for the notification
let notificationIdentifier = UUID().uuidString

You can create a random identifier using UUID, but you can also have custom identifiers for notifications that are managed manually by your application, like weekly-morning-notification.

Now that we have everything done we can create the UNNotificationRequest object. It represents a request to schedule a local notification, including the content of the notification and the trigger conditions for it to be delivered.

// 9. Create a notification request object
let notificationRequest = UNNotificationRequest(
	identifier: notificationIdentifier, // From step 8
	content: notificationContent,     // From step 1
	trigger: calendarTrigger         // From step 7
)

Scheduling Notifications

To schedule the notification you just need to use the notification center .add(_ request:) method. It is an asynchronous method that will throw an error in case anything goes wrong.

func add(_ request: UNNotificationRequest) async throws

Signature of the .add(_ request:) method.

// 10. Get the notification center shared instance
let notificationCenter = UNUserNotificationCenter.current()

// 11. Add the notification request to the notification center
do {
	try await notificationCenter.add(notificationRequest)
} catch {
	print("⛔️ \\(error.localizedDescription)")
}

And that's it, you are done! It is this simple to schedule local notifications.

If you are still skeptical and want to check if the notification was correctly scheduled you can request all the pending notifications to the notification center and iterate over them.

func checkPendingNotifications() async {
	let notificationCenter = UNUserNotificationCenter.current()
	let notificationRequests = await notificationCenter.pendingNotificationRequests()
        
	for notification in notificationRequests {
		print("> \(notification.identifier)")
	}
}

Example of how you can iterate over the pending notifications.

And if you want to cancel the scheduled notifications you can do so by using the notification center methods to remove all notifications that were already delivered, all the notifications that are pending, and only the pending notifications with an array of specific identifiers.

let notificationCenter = UNUserNotificationCenter.current()

// Removing all delivered notifications
notificationCenter.removeAllDeliveredNotifications()

// Removing all pending notifications
notificationCenter.removeAllPendingNotificationRequests()

// Removing pending notifications wiht specific identifiers
let notificationIdentifiers = ["weekly-morning-notification"]
notificationCenter.removePendingNotificationRequests(withIdentifiers: notificationIdentifiers)

Wrapping up

So far your application should be authorized to send notifications and creating and scheduling local notifications. In the next article, we are going to understand how we can react when a user interacts with our notifications and how to create custom actions to present to them.

You can complement this reading with the article Scheduling a Notification Locally from Your App in the official Apple documentation of the UserNotifications framework. Keep in mind that in there they are using the method signatures using completion handler instead of async/await.