如何知道推送通知权限提示已经显示

25

我想实现一个自定义屏幕,告知我的用户为什么要请求推送通知权限。在他们在该自定义屏幕中按下一个按钮后,我将使用[[UIApplication sharedApplication] registerForRemoteNotificationTypes:来呈现iOS推送通知权限对话框。

如果用户尚未看到推送通知权限对话框,我只想显示此自定义屏幕一次。我不能使用[[UIApplication sharedApplication] enabledRemoteNotificationTypes] == UIRemoteNotificationTypeNone,因为这也会返回“none”,如果用户决定不允许推送通知。

有任何想法吗?


用户怎么可能没有看到推送通知警报? - Muhammad Adnan
当您安装应用程序并首次运行时,用户尚未看到该应用程序的推送通知权限警报。 - Jovan
打开应用程序时,警报是显示的第一件事。用户无法不看到它。 - Bogdan Somlea
1
推送通知权限警告只会在调用[[UIApplication sharedApplication] registerForRemoteNotificationTypes:]时显示,而不是在应用程序启动时。 - Jovan
3个回答

6
你可以使用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
这种方法的问题在于,当用户删除应用程序并重新安装时,NSUserDefaults中的设置将消失,用户将再次看到自定义警报。一旦他/她选择了“是”,就什么也不会发生... - Jovan
是的,我同意你的观点。然而,卸载和重新安装应用程序并不是一种常见的行为。 - matt.P
2
同意,但如果有完美的解决方案,我更倾向于选择它。 - Jovan
4
当用户卸载应用后,在新的安装中会请求权限。 - micap
2
@micap 只有在卸载和重新安装之间经过了一天,才会执行此操作。但是,是的,这应该涵盖99.99%的所有情况,因此这似乎是最佳解决方案。 - Frank Rupprecht
如果用户清除了权限缓存,即:设置 > 通用 > 重置 > 重置位置与隐私,那该怎么办?如果在此操作后NSUserDefaults没有被清除,那将会出现问题。 - mr5

1

这只是一个解决办法,但在大多数情况下都有效。

iOS提示用户允许推送通知时,会调用applicationWillResignActive方法。

在调用registerForRemoteNotificationTypes...后,启动一个定时器(或dispatch_after),以便向用户显示一个新的警报,说明他们需要使用设置应用程序来启用通知。然后在applicationWillResignActive中取消该计时器。这样,只有当applicationWillResignActive从未被调用时,才会显示解释警报。

我唯一看到的问题是,如果应用程序在计时器正在运行的确切时间内因其他原因而退出活动状态...但这并不会使您处于更糟糕的境地,并且具有在大多数情况下工作的优点。


-1
我找到的解决方案有点取巧,但它能够工作。 你需要为两种不同的notificationSettings调用 registerUserNotificationSettings - 一种没有notificationCategory,另一种带有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];

在应用委托中,didRegisterUserNotificationSettings:(UIUserNotificationSettings *)notificationSettings 方法将被调用两次,而且不管用户在权限通知中的答案如何,在第二次调用之后,当前的通知设置将包含类别。只要类别计数大于0,就可以确定已显示通知权限对话框:
if ([UIApplication sharedApplication].currentUserNotificationSettings.categories.count > 0) {
    NSLog(@"Notifications permission has been asked");
} else {
    NSLog(@"Notifications permission hasn't been asked");
}

这告诉我权限尚未被询问,但对于我的设备来说显然已经询问过了。 - Robert Gummesson

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接