Registering for push notifications in SwiftUI
Learn how to request notification permissions and register for remote notifications in a SwiftUI app.
01 Jun 2026 · 7 min read
Push notifications allow us to inform users about updates even when they are not actively using the app.
Before an iOS app can receive remote notifications, we first need to register the app with Apple Push Notification service (APNs). This process includes requesting notification permission from the user, registering with APNs, and handling the generated device token.
In this article, we'll look at how to set up push notification registration in a SwiftUI app.
Let's dive in.

Overview
To register for push notifications, we need to:
- enable the push notifications capability
- request notification permission
- register with APNs
- handle the generated device token
Let's go through each step.
Enabling the push notifications capability
To enable push notifications, we first need to add the Push Notifications capability to the app target.
In Xcode, open the Signing & Capabilities tab and add the Push Notifications capability. This configures the required entitlement for the app and enables communication with APNs.
Requesting notification permission
Before the app can display notifications, the user needs to grant permission.
We can request authorization using UNUserNotificationCenter:
import UserNotificationsfunc requestNotificationPermission() async throws -> Bool {try await UNUserNotificationCenter.current().requestAuthorization(options: [.alert, .badge, .sound])}
The authorization options define which notification features the app would like to use:
In practice, it is usually best to request permission in context, for example when the user enables a feature that benefits from notifications, instead of immediately on app launch.
Checking existing authorization status
Before prompting, it's worth checking whether the user has already made a decision. This avoids redundant permission requests and lets us call registerForRemoteNotifications() directly if permission has already been granted:
func configureNotifications() async throws {let center = UNUserNotificationCenter.current()let settings = await center.notificationSettings()switch settings.authorizationStatus {case .notDetermined:let granted = try await center.requestAuthorization(options: [.alert, .badge, .sound])if granted {await registerForRemoteNotifications()}case .authorized, .provisional:await registerForRemoteNotifications()default:break}}@MainActorfunc registerForRemoteNotifications() {UIApplication.shared.registerForRemoteNotifications()}
Registering with APNs
Once permission has been granted, we can register the app with APNs:
UIApplication.shared.registerForRemoteNotifications()
This starts the registration process with Apple Push Notification service.
If registration succeeds, iOS generates a device token and passes it back to the app.
Integrating an AppDelegate in SwiftUI
Even in SwiftUI apps, remote notification registration callbacks are still delivered through the app delegate.
To integrate an app delegate into a SwiftUI app, we can use UIApplicationDelegateAdaptor:
@mainstruct ExampleApp: App {@UIApplicationDelegateAdaptor(AppDelegate.self)private var appDelegatevar body: some Scene {WindowGroup {ContentView()}}}
Receiving the device token
Once registration succeeds, the app delegate receives the generated device token:
final class AppDelegate: NSObject, UIApplicationDelegate {func application(_ application: UIApplication,didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data) {let tokenString = deviceToken.map { String(format: "%02.2hhx", $0) }.joined()print("Device token: \(tokenString)")// Send tokenString to your server}}
The device token is provided as Data, so we need to convert it to a hex string before sending it to a backend. The snippet above maps each byte to a zero-padded two-digit hex representation and joins them into a single string, which is the format most push notification services expect.
The token itself uniquely identifies the app installation on the device. In most cases it is forwarded to a backend server, which then uses it to send push notifications through APNs.
Handling registration failures
If registration fails, iOS calls a different app delegate method:
func application(_ application: UIApplication,didFailToRegisterForRemoteNotificationsWithError error: Error) {print("Failed to register: \(error)")}
This can happen, for example, if push notifications are unavailable on the device or if the simulator is used.
Testing push notification registration
Notification permissions and notification handling can both be tested in the simulator.
Xcode allows us to simulate remote notifications by sending .apns payload files to the app. This is useful for testing notification UI, payload handling, and navigation flows during development.
However, the simulator is not fully registered with Apple Push Notification service in the same way as a physical device. For example, real APNs delivery and production device token workflows should still be tested on actual hardware.
A note on device tokens
Device tokens are not guaranteed to stay the same forever.
For example, they can change after:
- reinstalling the app
- restoring a device backup
- switching devices
Because of this, apps should treat the device token as dynamic and keep the backend updated whenever a new token is received.
A note on provisional authorization
There is an additional authorization option worth knowing about: .provisional. It allows the app to deliver quiet notifications to Notification Center without showing the standard permission prompt upfront. The user can then decide whether to keep receiving notifications or turn them off.
While this can be useful for certain strategies, it is worth testing carefully. Provisional notifications are delivered quietly by default, and the exact upgrade path to prominent notifications can feel less predictable across iOS versions and user settings.



Newsletter
Like to support my work?
Say hi
Related tags
Articles with related topics
Latest articles and tips



