Logo for tanaschita.com

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:

  1. Enabling the push notification capability in the iOS application.
  2. Ask for user's permission to send notifications.
  3. Register with the Apple Push Notification service to receive a device token and send it to the server.
  4. 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.

Enable push notififications capabilities.
Enable push notififications capabilities in Xcode.

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.

options: [.alert, .badge, .sound]) { success, error in
guard success else {
// Handle error
// 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.


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.


Image of a reading marmot

Like to support my work?

Say hi

Related tags

Articles with related topics




Cheatsheet for the JSON payload of an iOS push notification

Learn the structure and configuration possibilities of a remote push notification.

17 Apr 2023 · 5 min read

Latest articles and tips

© 2024 tanaschita.com

Privacy policy