Introduction
To check whether a user has enabled push notifications on iOS, you use UNUserNotificationCenter.current().getNotificationSettings(). This async method returns a UNNotificationSettings object with an authorizationStatus property that tells you whether notifications are authorized, denied, provisional, or not yet requested. The approach differs between modern iOS (10+) and legacy versions, and you should always check status before attempting to send or schedule notifications.
Modern Approach: UNUserNotificationCenter (iOS 10+)
1import UserNotifications
2
3func checkNotificationStatus() {
4 UNUserNotificationCenter.current().getNotificationSettings { settings in
5 switch settings.authorizationStatus {
6 case .authorized:
7 print("Notifications are enabled")
8 case .denied:
9 print("Notifications are denied — user must enable in Settings")
10 case .notDetermined:
11 print("User hasn't been asked yet")
12 case .provisional:
13 print("Provisional notifications enabled (quiet delivery)")
14 case .ephemeral:
15 print("Ephemeral notifications (App Clips)")
16 @unknown default:
17 print("Unknown status")
18 }
19 }
20}
The callback runs on a background thread — dispatch to the main queue for UI updates:
1UNUserNotificationCenter.current().getNotificationSettings { settings in
2 DispatchQueue.main.async {
3 if settings.authorizationStatus == .authorized {
4 self.showNotificationBadge()
5 } else {
6 self.showEnableNotificationsPrompt()
7 }
8 }
9}
Checking Individual Notification Types
Beyond the overall authorization, you can check specific delivery methods:
1UNUserNotificationCenter.current().getNotificationSettings { settings in
2 print("Alerts: \(settings.alertSetting == .enabled)")
3 print("Badges: \(settings.badgeSetting == .enabled)")
4 print("Sounds: \(settings.soundSetting == .enabled)")
5 print("Lock screen: \(settings.lockScreenSetting == .enabled)")
6 print("Notification center: \(settings.notificationCenterSetting == .enabled)")
7 print("Critical alerts: \(settings.criticalAlertSetting == .enabled)")
8
9 // Each setting can be .enabled, .disabled, or .notSupported
10}
A user might have notifications authorized but alerts disabled — they would only receive badge updates.
Requesting Permission
If the status is .notDetermined, request permission:
1func requestNotificationPermission() {
2 UNUserNotificationCenter.current().getNotificationSettings { settings in
3 guard settings.authorizationStatus == .notDetermined else { return }
4
5 UNUserNotificationCenter.current().requestAuthorization(
6 options: [.alert, .badge, .sound]
7 ) { granted, error in
8 if granted {
9 DispatchQueue.main.async {
10 UIApplication.shared.registerForRemoteNotifications()
11 }
12 }
13 if let error = error {
14 print("Error requesting notifications: \(error)")
15 }
16 }
17 }
18}
Using async/await (iOS 15+)
1func checkAndRequestNotifications() async -> Bool {
2 let center = UNUserNotificationCenter.current()
3 let settings = await center.notificationSettings()
4
5 switch settings.authorizationStatus {
6 case .authorized, .provisional:
7 return true
8 case .notDetermined:
9 do {
10 let granted = try await center.requestAuthorization(options: [.alert, .badge, .sound])
11 if granted {
12 await MainActor.run {
13 UIApplication.shared.registerForRemoteNotifications()
14 }
15 }
16 return granted
17 } catch {
18 return false
19 }
20 case .denied, .ephemeral:
21 return false
22 @unknown default:
23 return false
24 }
25}
Directing Users to Settings
Once a user denies notifications, you cannot re-prompt them. The only option is to direct them to the Settings app:
1func openNotificationSettings() {
2 if let url = URL(string: UIApplication.openSettingsURLString) {
3 UIApplication.shared.open(url)
4 }
5}
6
7// Show a custom UI explaining why they should enable notifications
8func promptToEnableInSettings() {
9 let alert = UIAlertController(
10 title: "Enable Notifications",
11 message: "Turn on notifications in Settings to receive updates.",
12 preferredStyle: .alert
13 )
14 alert.addAction(UIAlertAction(title: "Open Settings", style: .default) { _ in
15 self.openNotificationSettings()
16 })
17 alert.addAction(UIAlertAction(title: "Not Now", style: .cancel))
18 present(alert, animated: true)
19}
SwiftUI Integration
1import SwiftUI
2import UserNotifications
3
4class NotificationManager: ObservableObject {
5 @Published var isAuthorized = false
6 @Published var isDenied = false
7
8 func checkStatus() {
9 UNUserNotificationCenter.current().getNotificationSettings { settings in
10 DispatchQueue.main.async {
11 self.isAuthorized = settings.authorizationStatus == .authorized
12 self.isDenied = settings.authorizationStatus == .denied
13 }
14 }
15 }
16}
17
18struct ContentView: View {
19 @StateObject private var notifications = NotificationManager()
20
21 var body: some View {
22 VStack {
23 if notifications.isAuthorized {
24 Text("Notifications are enabled")
25 } else if notifications.isDenied {
26 Button("Enable in Settings") {
27 if let url = URL(string: UIApplication.openSettingsURLString) {
28 UIApplication.shared.open(url)
29 }
30 }
31 }
32 }
33 .onAppear { notifications.checkStatus() }
34 }
35}
Legacy Approach (pre-iOS 10)
1// Deprecated — only use for iOS 9 and earlier support
2if UIApplication.shared.isRegisteredForRemoteNotifications {
3 let types = UIApplication.shared.currentUserNotificationSettings?.types ?? []
4 if types.contains(.alert) || types.contains(.badge) || types.contains(.sound) {
5 print("Notifications enabled")
6 }
7}
Common Pitfalls
Checking status synchronously: getNotificationSettings is async. Calling it and immediately checking a flag before the callback runs gives stale results. Always use the completion handler or await.
Confusing .authorized with registered for remote: authorizationStatus == .authorized means the user approved local and remote notification display. You still need to call registerForRemoteNotifications() separately to get a device token for push.
Re-requesting after denial: requestAuthorization does nothing if the user already denied — it returns false immediately without showing a prompt. You must direct users to Settings.
Not rechecking on app foreground: Users can change notification settings at any time. Check status in applicationDidBecomeActive or sceneDidBecomeActive to stay current.
Provisional notifications: .provisional means quiet delivery (notification center only, no alerts or sounds). Do not treat it the same as .authorized for features that rely on visible alerts.
Summary
Use UNUserNotificationCenter.current().getNotificationSettings() to check notification status (iOS 10+)
Check authorizationStatus for overall permission and individual settings (alerts, badges, sounds) for specific capabilities
Request permission only when status is .notDetermined — denied users must go to Settings
Use UIApplication.openSettingsURLString to deep-link users to your app's Settings page
Recheck notification status on every app foreground since users can change settings at any time
Use async/await on iOS 15+ for cleaner notification permission flows