detect "Allow Notifications" is on/off for iOS8

33,574

Solution 1

Method enabledRemoteNotificationTypes is deprecated since iOS8.

To check remote notifications status in iOS8 you can call

[[UIApplication sharedApplication] isRegisteredForRemoteNotifications];

it will return NO if user disable notifications in Settings. Documentation on isRegisteredForRemoteNotifications

Or you can retrieve all current notification settings:

[[UIApplication sharedApplication] currentUserNotificationSettings];

Documentation on currentUserNotificationSettings

Solution 2

Swift 3+

let isRegisteredForLocalNotifications = UIApplication.shared.currentUserNotificationSettings?.types.contains(UIUserNotificationType.alert) ?? false

Swift 2.3

let isRegisteredForLocalNotifications = UIApplication.sharedApplication().currentUserNotificationSettings()?.types.contains(UIUserNotificationType.Alert) ?? false

Solution 3

I apologize for this answer/comment if it is in the wrong place. I am REALLY new at iOS programming and have never posted to stack overflow before. I think this should actually be a comment, but without a 50 rating I am not allowed. I also apologize if the explanation is somewhat rudimentary, but again, kind of new :).

I also wished to test for whether a user has changed what notifications are allowed/required by my app after the initial request. After trying to decipher the Apple documentation (the writers at Apple are either much smarter than I am, or the documentation is purposely obscure) and doing a bit of testing I tested for the value of

[[UIApplication sharedApplication] currentUserNotificationSettings].hash.

I believe that this returns a three bit hash value where bit one is for Banner notifications, bit 2 is for Sound notifications, and bit 3 is for Alert notifications.

So...

000 = 0 = no notifications.
001 = 1 = only banner,
010 = 2 = only sound,
011 = 3 = sound and banner, no alert
100 = 4 = only alert notifications
and so on until,
111 = 7 = all notifications on.

This also shows 0 if Allow Notifications is turned off in the Settings app. Hope this helps.

Solution 4

To check the remote notifications status in iOS8 and iOS9 you call:

// Obj-C
[[UIApplication sharedApplication] isRegisteredForRemoteNotifications]; 
// Swift
UIApplication.sharedApplication().isRegisteredForRemoteNotifications

It returns true if your app can receive remote notifications. However receiving remote notifications does not mean it will also display them to the user.

The request registerForRemoteNotifications() succeeds in almost every case and the AppDelegate's didRegisterForRemoteNotificationsWithDeviceToken is called which gives you the device token. The app can then receive silent remote notifications that are not displayed to the user. You can for example trigger background processes in the app when such a notification is received. See Documentation.

To not only receive but also display remote notifications to the user you request permission with:

// Swift
let notificatonSettings = UIUserNotificationSettings(forTypes: [.Badge, .Alert, .Sound], categories: nil)
UIApplication.sharedApplication().registerUserNotificationSettings(notificatonSettings)

This will display a dialog to the user where they can allow or deny your request. Indifferent of their decision the app will still be able to receive remote notifications.

If the users allows, AppDelegate's didRegisterForRemoteNotificationsWithDeviceToken is called.

To check whether the user allowed or denied your request or in fact changed the notifications permissions later in iOS setting you call:

// Obj-C
[[UIApplication sharedApplication] currentUserNotificationSettings];
// Swift
UIApplication.sharedApplication().currentUserNotificationSettings()   

See Documentation.

Solution 5

This should work the very first time your app is launched user will get a dialog, to check if user denies or allows notifications, use:

-(void)application:(UIApplication *)application didRegisterUserNotificationSettings:   (UIUserNotificationSettings *)notificationSettings
{
    if (notificationSettings.types) {
        NSLog(@"user allowed notifications");
        [[UIApplication sharedApplication] registerForRemoteNotifications];
    }else{
        NSLog(@"user did not allow notifications");
        // show alert here
    }
}

On consecutive launches, use:

[[UIApplication sharedApplication] isRegisteredForRemoteNotifications];
Share:
33,574
JosephT
Author by

JosephT

Updated on January 02, 2020

Comments

  • JosephT
    JosephT over 4 years

    I am trying to detect the Local notification settings for the App in iOS 8

    for UIUserNotificationSettings, it returns me 7 as I have turned on all Badge, Sound & Alert.

    In the setting, I switch off "Allow Notification" , the app still return me 7 for UIUserNotificationSettings (Badge, Sound & Alert on). Is there a way to detect "Allow Notification" on/off?

    - (void)application:(UIApplication *)application
        didRegisterUserNotificationSettings:(UIUserNotificationSettings *)notificationSettings{
    
        NSLog(@"---notificationSettings.types %d" , notificationSettings.types );
        if(notificationSettings.types!=7){
            UIAlertView * alert =[[UIAlertView alloc ] initWithTitle:@"Please turn on Notification"
                                                             message:@"Go to Settings > Notifications > App.\n Switch on Sound, Badge & Alert"
                                                            delegate:self
                                                   cancelButtonTitle:@"Ok"
                                                   otherButtonTitles: nil];
            [alert show];
        }
    }
    
  • JosephT
    JosephT almost 10 years
    thanks for the answer. but this can't tell if user has choose switch "allow notification" on/off. In my case it always return UIRemoteNotificationTypeNone.
  • Ponf
    Ponf almost 10 years
    enabledRemoteNotificationTypes is deprecated since iOS8
  • JosephT
    JosephT almost 10 years
    Thanks, I found that it can only return UIUserNotificationType from (UIUserNotificationSettings *)currentUserNotificationSettings, which can only tell sound, alert or badge is on/off. But this value always return the same regardless of App's "Allow Notification" is on or off. If "Allow Notication" is off, no notification is received at all, although the UIUserNotificationType may tell you badge, sound, alert is on.
  • Ponf
    Ponf almost 10 years
    JosephT, isRegisteredForRemoteNotifications will be NO if user has disabled notifications in Settings, so I think it's exactly what you need
  • Daniel Baughman
    Daniel Baughman almost 10 years
    I don't think this is right... my testing reveals that if the user has "allow notifications" enabled, but then has alert types set to none, and "sounds" disabled in the notification then "isRegisteredForRemoteNotifications" will return false.
  • Maxim Kholyavkin
    Maxim Kholyavkin over 9 years
    it looks like isRegisteredForRemoteNotifications always NO when app uses local notifications only...
  • James
    James over 9 years
    This is exactly what I needed. No one ever says that if they previously said no to receiving notifications it would still get to this point and never call didFailToRegsiterForRemoteNotifications. I just needed this script so I could still call my own function.
  • Jonathon Horsman
    Jonathon Horsman over 9 years
    @Ponf I think your description is subtly incorrect. You say "[[UIApplication sharedApplication] isRegisteredForRemoteNotifications]; it will return NO if user disable notifications in Settings" but the documentation says "This method reflects only the successful completion of the remote registration process that begins when you call the registerForRemoteNotifications method". This means if the user allows notifications when prompted, then goes into settings and disables them, the isRegisteredForRemoteNotifications will still return true
  • Ponf
    Ponf over 9 years
    @JonathonHorsman in the first paragraph of Apple's docs: NO if registration has not occurred, has failed, or has been denied by the user.. I think by the last part "has been denied" they mean disabling remote notifications in settings. You can easily test it :)
  • Jonathon Horsman
    Jonathon Horsman over 9 years
    Hi @Ponf that's what I thought but sadly it doesn't reflect a change made in the settings after the user allows notifications, then goes into settings and disables them. I've tested this and get true for isRegisteredForRemoteNotifications despite the setting being disabled.
  • Will
    Will over 9 years
    agreeing with @JonathonHorsman, it's returning true for me despite turning it off in the settings.
  • Will
    Will over 9 years
    Can anyone else confirm that once a user turns on his notifications in settings after agreeing to it initially that the method isRegisteredForRemoteNotifications will return NO?
  • jammyman34
    jammyman34 over 9 years
    I don't know what the deal is, but using isRegisteredForRemoteNotifications() has never returned true regardless of whether I accept or reject registration, accept registration (then turn off), reject registration (then turn on)... I also get a println() of false. This is all done in the simulator, resetting the settings each test. I'm at a loss as to how to know if the setting has been done or not.
  • jammyman34
    jammyman34 over 9 years
    Hey, this is great, but I can't figure out how to get it to not trigger a notification if badge or sound is toggled off in the notifications (I only care about the alert). Any thoughts?
  • AsTeR
    AsTeR over 9 years
    Well settings.types contains the actual configuration, that tells you what if a feature is enable. I guess (but I'm not sure) that you can test using things like setting.types & UIUserNotificationType.Badge, then you make some updatedWishedTypes than you can use to configure your notifications: UIUserNotificationSettings(forTypes: updatedWishedTypes, categories: nil);. Hope that helps.
  • Ponf
    Ponf over 9 years
    @jammyman34 are you testing this method on device or simulator? It works correct for me only on device.
  • jammyman34
    jammyman34 over 9 years
    @Ponf I actually gave up on the above based on my printlin() results always returning false regardless of the actual settings. I was able to get AsTeR's working as needed though. His suggested code is 2 below this one.
  • newshorts
    newshorts almost 9 years
    be cautious when using this approach, the user may later set notifications to none in their settings. be sure to check what settings are allowed each time you use a usernotification.
  • lupinglade
    lupinglade almost 9 years
    While these may be the correct flag values, using the hash property of NSObject is incorrect for this as it is not at all the "value" of the object - it is just a hash for comparison purposes. No one should ever rely on this for the value. Instead use currentUserNotificationSettings's value which is an NSUserNotificationSettings object with the right properties for querying.
  • lupinglade
    lupinglade almost 9 years
    isRegisteredForRemoteNotifications will be true if Background Refresh is enabled, even if the user has visual push notifications disabled in Settings.
  • lupinglade
    lupinglade almost 9 years
    Do not use the .hash property ( there is no hashValue property). Use the currentUserNotificationSettings value itself. Its a UIUserNotificationSettings object and you can compare against the types property.
  • anoop4real
    anoop4real almost 9 years
    isRegisteredForRemoteNotifications always returning me true once I have activated the notification. Even after I disable it from the settings it is still giving me an yes. :( @JonathonHorsman are you able to figure out some solution for this?
  • BaSha
    BaSha over 8 years
    @anoop4real: facing same, any accurate way to read latest status from settings?
  • megimix
    megimix over 8 years
    @JonathonHorsman from my experience you are right, my question is how to detect if the user manually disable push from setting after he approve in the prompt?
  • richc
    richc about 8 years
    Hi Manuel - is there a way to track if the notification settings have changed, rather than just current status? Maybe I should set my own NSUserDefaults flag?
  • Manuel
    Manuel about 8 years
    @richc As of iOS 9.3 you can only check the current authentication status. "Remembering" the current notification authentication status in NSUserDefaults and checking against it to detect permission changes is definitely a good practical option I have seen many times. Unfortunately there is no equivalent to location permission changes yet which trigger a function 'locationManager(manager: CLLocationManager, didChangeAuthorizationStatus status: CLAuthorizationStatus)' whenever the user changes the permission in iOS settings. Hopefully iOS 10 will come to the rescue.
  • richc
    richc about 8 years
    Hi Manuel - this rather long winded check is what I put in applicationDidBecomeActive. It works fine. let currentStatus = application.currentUserNotificationSettings() let currentStatusBool = currentStatus!.types.contains(.Badge) let previousStatus = NSUserDefaults.standardUserDefaults().boolForKey("userNotifi‌​cationSettings") if currentStatusBool == true && previousStatus == true { // .Badge is a valid option and previous status is true, therefore nothing has changed, so do nothing } and so on for the other 3 combinations. Thx again.
  • DawnSong
    DawnSong over 6 years
    Here is a special case: if you disable Sounds and Badge, keep alert style is none, and enable "Show in Notification Center"(在“通知中心”显示) and "Show on lock screen"(在锁定屏幕显示), you will get currentUserNotificationSettings?.types.rawValue == 0; but the truth is that you can receive notification and open it in Notification Center. It's really strange.
  • DawnSong
    DawnSong over 6 years
    First of all, do NOT use excalamation mark. Second, types.contains(.none) always returns true.