Developer guide on push notifications for iOS
Learn how to setup and handle remote push notifications.
21 May 2023 · 5 min read
Push notifications allow us to inform the user even if they are not currently using our app.
While local notifications are fully controlled and send by the app itself, push notifications, also called remote notifications, are send by a server using the Apple Push Notification service.
To setup push notifications, we need to perform the following main tasks:
- Enabling the push notification capability in the iOS application.
- Ask for user's permission to send notifications.
- Register with the Apple Push Notification service to receive a device token and send it to the server.
- Use callbacks in the app to handle push notifications.
Let's look at each step in more detail.
1. Enable push notifications
To enable push notifications in an iOS application, we need to add the push notifications capability by tapping the + Capability button in the Signing & Capabilities tab.

Alternatively, we can do the same by logging in into the Apple Developer Center and adding the push notifications entitlement to the associated App ID. That's what Xcode does behind the scenes if we choose the above approach.
2. Asking user's permission
Before registering for push notification, we need to ask the user's permission to send notifications, for example on app start or when the user activates or starts using a certain feature.
UNUserNotificationCenter.current().requestAuthorization(options: [.alert, .badge, .sound]) { success, error inguard success else {// Handle errorreturn}// Register for push notifications}
As options, the requestAuthorization method takes an UNAuthorizationOptions type.
With [.alert, .badge, .sound], we ask the user for the ability to display alerts, to update the app’s badge and to play sounds.
3. Register for push notifications
If the permission request succeeds, we can register with the Apple Push Notification service which has to know the address of a user's device before it is able send notifications to that device.
UIApplication.shared.registerForRemoteNotifications()
The above call initiates the registration process with the Apple Push Notification service. If it succeeds, the app calls the app delegate's application(_:didRegisterForRemoteNotificationsWithDeviceToken:) method and passes it a device token:
func application(_ application: UIApplication, didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data) {print("Device Token: \(deviceToken)")// Send device token to server}
The device token is provided by APNs and uniquely identifies our app on the particular device. After receiving it, we can pass the device token to the server.
If the registration fails, the app calls its app delegate’s application(\_:didFailToRegisterForRemoteNotificationsWithError:) method instead:
func application(_ application: UIApplication, didFailToRegisterForRemoteNotificationsWithError error: Error) {print("Failed to register: \(error)")}
To learn how to integrate the mentioned app delegate methods in a SwiftUI application, check out this article on understanding the difference between AppDelegate, SceneDelegate and SwiftUI's App protocol.
Since remote notifications are not supported in the simulator, a device is needed to successfully receive a device token. Nevertheless, we can simulate a notification in the simulator.
4. Handle push notifications
When receiving a push notification, we might want to handle it in the iOS application, for example:
- to react when a user taps on a push notification while our app is terminated
- to react when a user taps on a push notification while our app is running
- to respond to a notification action selected by a user. Check out this article on how to add custom actions to notifications to learn more.
Let's look at first two use cases in more detail.
Reacting when a user taps on a push notification while our app is terminated
When our app isn't running and a user launches it by tapping a push notification, iOS passes the notification within the launchOptions argument of application(_:didFinishLaunchingWithOptions:):
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {if let options = launchOptions,let notification = options[.remoteNotification] as? [String: Any] {let aps = notification["aps"] as? [String: Any]let someCustomKey = notification["someCustomKey"] as? String// Handle notification tap}}
As shown above, we can use the notification dictionary to get the data we need to handle it. Check out this cheat sheet on the anatomy of a push notification to learn more about the json payload of a push notification.
Reacting when a user taps on a push notification while our app is running
When a user taps on the push notification while the app is in the background or foreground, the app delegate's application(_:didReceiveRemoteNotification:fetchCompletionHandler:) method is called:
func application(_ application: UIApplication, didReceiveRemoteNotification userInfo: [AnyHashable : Any], fetchCompletionHandler completionHandler: @escaping (UIBackgroundFetchResult) -> Void) {let aps = userInfo["aps"] as? [String: Any]let someCustomKey = userInfo["someCustomKey"] as? String// Handle notification}
Similar to the previous example, we can use the passed in userInfo dictionary to get the notification's payload.
Newsletter
Like to support my work?
Say hi
Related tags
Articles with related topics
Latest articles and tips