25
votes

I want to implement a custom screen that informs my users why I'm about to ask for push notification permissions. After they press a button in that custom screen I present the iOS push notification permission dialog with [[UIApplication sharedApplication] registerForRemoteNotificationTypes:

I only want to show this custom screen once if the user hasn't already seen the push notification permission dialog. I cannot use [[UIApplication sharedApplication] enabledRemoteNotificationTypes] == UIRemoteNotificationTypeNone as this will also return 'none' if the user decided to not allow push notifications.

Any ideas anyone?

3
how is it possible that user has not seen push notification alert? - Muhammad Adnan
When you install the app and run it for the very first time, the user hasn't seen the push notification permission alert for the app yet. - Jovan
the alert is the first thing shown when you open the app. there is no way for the user not to see it - Bogdan Somlea
The push notification permission alert is only shown when you call [[UIApplication sharedApplication] registerForRemoteNotificationTypes: and not at application startup - Jovan

3 Answers

6
votes

You could use NSUserDefaults :

#define kPushNotificationRequestAlreadySeen @"PushNotificationRequestAlreadySeen"

if(![[NSUserDefaults standardUserDefaults] boolForKey:kPushNotificationRequestAlreadySeen]) {

    // Notify the user why you want to have push notifications
    UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:... delegate:self ...];
    [alertView show];

    [[NSUserDefaults standardUserDefaults] setBool:YES forKey:kPushNotificationRequestAlreadySeen];
}
else {
    // Already allowed -> register without notifying the user
    [[UIApplication sharedApplication] registerForRemoteNotificationTypes:UIRemoteNotificationTypeAlert | UIRemoteNotificationTypeBadge | UIRemoteNotificationTypeSound];
}

And

- (void)alertView:(UIAlertView*)alertView didDismissWithButtonIndex:(NSInteger)index {
    // Actually registering to push notifications
    [[UIApplication sharedApplication] registerForRemoteNotificationTypes:UIRemoteNotificationTypeAlert | UIRemoteNotificationTypeBadge | UIRemoteNotificationTypeSound];
}
1
votes

This is just a work-around but will work in the majority of cases.

When iOS prompts the user to allow push notifications, applicationWillResignActive is called.

After calling registerForRemoteNotificationTypes...start a timer (or dispatch_after) that will show a new alert to the user explaining that they'll need to use the Settings app to enable notifications. Then in applicationWillResignActive cancel the timer. This way, the explanation alert will only show if applicationWillResignActive is never called.

The only problem I see with this is if the app resigns active for other reasons at the exact time that the timer is going...but this puts you in no worse a situation that you're already in and has the advantage of working in the majority of cases.

-1
votes

The solution that I've found is a bit of a hack, but it works. You need to call registerUserNotificationSettings for two different notificationSettings - one without a notificationCategory and one with a notificationCategory:

        //Request notification permission
    UIUserNotificationSettings *notificationSettings = [UIUserNotificationSettings settingsForTypes:UIUserNotificationTypeAlert | UIUserNotificationTypeBadge | UIUserNotificationTypeSound categories:nil];
    [[UIApplication sharedApplication] registerUserNotificationSettings:notificationSettings];

    //Request notification permission again, but with a category with no actions
    UIMutableUserNotificationCategory *category = [[UIMutableUserNotificationCategory alloc] init];
    category.identifier = @"com.xyz.markNotificationPopupShownCategoryIdentifier";

    UIUserNotificationSettings *notificationSettingsWithCategory = [UIUserNotificationSettings settingsForTypes:UIUserNotificationTypeAlert | UIUserNotificationTypeBadge | UIUserNotificationTypeSound categories:[NSSet setWithObject:category]];
    [[UIApplication sharedApplication] registerUserNotificationSettings:notificationSettingsWithCategory];

The didRegisterUserNotificationSettings:(UIUserNotificationSettings *)notificationSettings method in the app delegate will be called two times, and irrespective of the user's answer in the permission notification, after the second call, the current notification settings will contain the category. As long as the category count is greater than 0, you can know for sure that the notifications permission dialog has been shown:

if ([UIApplication sharedApplication].currentUserNotificationSettings.categories.count > 0) {
    NSLog(@"Notifications permission has been asked");
} else {
    NSLog(@"Notifications permission hasn't been asked");
}