Requesting User Authorization for Notifications with async/await

Requesting User Authorization for Notifications with async/await

By the end of this tutorial, you will be able to request authorization to send notifications using the UserNotifications framework.

If you want to create user-oriented notifications in your iOS application, you might stumble across two frameworks with very similar names, Notification Center and User Notifications.

The correct framework to use if you want to schedule local notifications in your iOS application is the User Notifications framework. Even though they have very similar names they have very different functionalities. In fact, the Notification Center framework is being replaced by WidgetKit right now.

To be able to send notifications to the user of your application you must first ask for authorization. In this tutorial, we will cover how to request authorization and how to check the current authorization status for your application.

Since Swift 5.5 brought the concepts of async/await, most of the asynchronous methods and functions of various frameworks have been updated to support it. This tutorial will focus on the asynchronous version of these functions.

Requesting Authorization

The first thing you must do to be able to send notifications to your users is to ask them for permission. It is a simple procedure in which you define what types of notifications you want to be able to send and once you request authorization the system will show an alert in which the user will give the app authorization (or not) to send them notifications of that type.

UNAuthorizationOptions.badge // Updated the badge of the app
UNAuthorizationOptions.sound // Play sounds when notifying
UNAuthorizationOptions.alert // The ability to show the notification banner

Most common types of notification. More at UNAuthorizationOptions documentation.

Requesting authorization is an asynchronous task and as of Swift 5.5 and iOS 15, you can use the new asynchronous method signatures.

// 1. Asynchronous function that throws errors
func requestAuthorizationForNotifications() async throws -> Bool {
	// 2. Get the shared instance of UNUserNotificationCenter
	let notificationCenter = UNUserNotificationCenter.current()
	// 3. Define the types of authorization you need
	let authorizationOptions: UNAuthorizationOptions = [.alert, .sound, .badge]

	do {
		// 4. Request authorization to the user
		let authorizationGranted = try await notificationCenter.requestAuthorization(options: authorizationOptions)
		// 5. Return the result of the authorization process
		return authorizationGranted
	} catch {
		throw error
	}
}
  1. Create a function called requestAuthorizationForNotifications. It must be an asynchronous function that throws an error.
  2. Get the shared instance of the user notification center and store it in a constant named notificationCenter.
  3. Define the types of authorization you will need by creating an array of UNAuthorizationOptions
  4. In a do/catch block request user authorization from the notification center using the method requestAuthorization(options:), passing the authorizationOptions to it. Since this is an asynchronous method you must use the keyword await before calling the method. In case of failure, the method will throw an error, so you must also add the try keyword. Store the result of the operation in a constant called authorizationGranted.
  5. Return the result of the authorization process. Throw the error thrown by the requestAuthorization(options:) method, in case something goes wrong.

Now you can call this method once your application needs to set up notifications. It can be on your onboarding process or when the user activates a behavior in your application in which you must notify them.

async {
	do {
		let _ = try await requestAuthorizationForNotifications()
	} catch {
		print(error.localizedDescription)
	}
}

Example of how you can use the requestAuthorizationForNotifications function in a synchronous context.

You can find more about requesting authorization in the article Asking Permission to Use Notifications at the Apple official documentation.

Checking the Current Authorization Status

Other parts of your application might need to know if authorization has been granted before triggering certain features. You can do it by accessing the notification settings from the user notification center.

func checkCurrentAuthorizationSetting() async {
    let notificationCenter = UNUserNotificationCenter.current()
    // Request the current notification settings
    let currentSettings = await notificationCenter.notificationSettings()
    
	...
}

The notification settings object is defined by the class UNNotificationSettings. This object contains information regarding:

switch currentSettings.authorizationStatus {
    case .authorized:
    	// Code here
    case .denied:
	    // Code here
    case .ephemeral:
    	// Code here
    case .notDetermined:
	    // Code here
    case .provisional:
    	// Code here
    @unknown default:
	    // Code here
}

Each specific setting is represented by a different property. They can be .enabled, .disabled or .notSupported.

currentSettings.alertSetting == .enabled
currentSettings.badgeSetting == .enabled
currentSettings.soundSetting == .enabled
currentSettings.announcementSetting == .enabled
currentSettings.carPlaySetting == .enabled
currentSettings.lockScreenSetting == .enabled
currentSettings.criticalAlertSetting == .enabled

Based on this information you can set up your app's notification-related behaviors.

Wrapping up

Now that your application is authorized to send notifications you can create and schedule notifications requests. We will explore how to do it on the tutorial Creating and Scheduling Local Notifications with async/await, coming out next week.

For information regarding designing great notification experiences take a look at the Human Interface Guidelines for notifications, at the Apple developer portal.

Managing notifications | Apple Developer Documentation
Notifications can give people timely and important information, whether the device is locked or in use.