I am building an app that targets iOS7 and iOS8. I ask the user for permission to send push notifications. But for some reason, neither iOS7 nor iOS8 ever calls my application:didFailToRegisterForRemoteNotificationsWithError
handler if I click "No" when asked for push permission.
我正在构建一个针对iOS7和iOS8的应用程序。我要求用户发送推送通知的权限。但由于某些原因,iOS7和iOS8都没有调用我的应用程序:didFailToRegisterForRemoteNotificationsWithError处理程序,如果我在被要求获取推送权限时单击“否”。
My question: how do I know, on both iOS7 and iOS8, when the user has dismissed the request for push notifications--and how do I know if they denied the request?
我的问题:我在iOS7和iOS8上如何知道用户何时驳回了推送通知的请求 - 我怎么知道他们是否拒绝了请求?
I've looked at a bunch of * answers and have implemented what they suggest, but it's not working as documented:
我已经查看了一堆*的答案并实现了他们的建议,但它没有按照记录的方式工作:
- iOS7: if the user approves the request, the system does call my
application:didRegisterForRemoteNotificationsWithDeviceToken:
handler. So I can tell that they approved it. But if the user denies the request then I don't get a callback toapplication:didFailToRegisterForRemoteNotificationsWithError
. This seems like a bug, and I can't tell that the user denied the request. - iOS7:如果用户批准了请求,系统会调用我的应用程序:didRegisterForRemoteNotificationsWithDeviceToken:handler。所以我可以告诉他们批准了它。但是如果用户拒绝请求,那么我就不会收到应用程序的回调:didFailToRegisterForRemoteNotificationsWithError。这似乎是一个错误,我不能告诉用户拒绝了该请求。
- iOS8: if the user approves or denies the request, the system does call my
application:didRegisterUserNotificationSettings
handler. I can look at thenotificationSettings
parameter to see if the user approved or denied my request, so that's handy.However, if I subsequently callUpdate: if I subsequently callisRegisteredForRemoteNotifications()
(e.g., when the app becomes active later on), it always returns true--even if the user had denied the request. So I get a false positive. This seems like a bug and I see that others have noticed this as well.let settings = UIApplication.sharedApplication().currentUserNotificationSettings()
, I can checksettings.types
to see if alerts are allowed. So for iOS8, it looks like I'm all set. - iOS8:如果用户批准或拒绝请求,系统会调用我的应用程序:didRegisterUserNotificationSettings handler。我可以查看notificationSettings参数,看看用户是否批准了我的请求,这样很方便。但是,如果我随后调用isRegisteredForRemoteNotifications()(例如,当应用程序稍后变为活动状态时),它总是返回true - 即使用户拒绝了该请求。所以我得到了误报。这似乎是一个错误,我看到其他人也注意到了这一点。更新:如果我随后调用let settings = UIApplication.sharedApplication()。currentUserNotificationSettings(),我可以检查settings.types以查看是否允许警报。所以对于iOS8来说,看起来我已经完成了设置。
I'm using an NSUserDefaults
boolean to keep track of whether I've already asked the user to grant permission.
我正在使用NSUserDefaults布尔来跟踪我是否已经要求用户授予权限。
I am using hardware devices for testing (iPhone 4S with iOS7 and iPhone 5 with iOS8), not a simulator.
我正在使用硬件设备进行测试(带有iOS7的iPhone 4S和带有iOS8的iPhone 5),而不是模拟器。
I am resetting my device after each test, to make it show the request alert again.
我在每次测试后重置我的设备,以使其再次显示请求警报。
Here's how I register for push notifications. The if
branch is taken on iOS8 and the else
branch is taken on iOS7:
这是我如何注册推送通知。 if分支在iOS8上进行,而else分支在iOS7上进行:
let application = UIApplication.sharedApplication()
if (application.respondsToSelector("registerUserNotificationSettings:")) {
let settings = UIUserNotificationSettings(forTypes: .Badge | .Alert | .Sound,
categories: nil )
application.registerUserNotificationSettings(settings)
} else {
application.registerForRemoteNotificationTypes(.Badge | .Alert | .Sound)
}
(In iOS8, when application:didRegisterUserNotificationSettings:
is called, I then call application.registerForRemoteNotifications()
).
(在iOS8中,当调用application:didRegisterUserNotificationSettings:时,我调用application.registerForRemoteNotifications())。
3 个解决方案
#1
5
Your didFailToRegisterForRemoteNotificationsWithError
method isn't called, because the registration didn't fail - it was never even attempted because the user denied the request.
您的didFailToRegisterForRemoteNotificationsWithError方法未被调用,因为注册没有失败 - 甚至从未尝试过,因为用户拒绝了请求。
On iOS7 you can do a couple of things:
在iOS7上,您可以做以下几件事:
- Assume that remote notifications aren't available until
didRegisterForRemoteNotificationsWithDeviceToken
is called - 假设在调用didRegisterForRemoteNotificationsWithDeviceToken之前,远程通知不可用
- Check the value
enabledRemoteNotificationTypes
on theUIApplication
object - 检查UIApplication对象上的值enabledRemoteNotificationTypes
#2
7
I was trying to find a way around this same issue.
我试图找到绕过同样问题的方法。
When the push notification permission UIAlert is shown, it is shown from outside of my app. Once the user has selected "Don't Allow" or "OK", my app is becoming active again.
当显示推送通知权限UIAlert时,它会从我的应用程序外部显示。一旦用户选择“不允许”或“确定”,我的应用程序将再次变为活动状态。
I have a view controller that I'm presenting before prompting the user for Push permissions. In this view controller I listen for the UIApplicationDidBecomeActiveNotification
, and then dismiss my view controller.
在提示用户输入推送权限之前,我有一个视图控制器。在这个视图控制器中,我监听UIApplicationDidBecomeActiveNotification,然后关闭我的视图控制器。
This has been working pretty well, whereas every other solution I've seen hasn't worked for me at all.
这一直很好用,而我见过的所有其他解决方案根本不适用于我。
#3
2
Assuming that you're compiling against iOS8 or newer, you can use the following delegate method:
假设您正在针对iOS8或更新版本进行编译,您可以使用以下委托方法:
func application(application: UIApplication, didRegisterUserNotificationSettings notificationSettings: UIUserNotificationSettings) {
print("Notifications status: \(notificationSettings)")
}
then on your didFinishLaunching (or where is appropriate for your needs) you must invoke:
然后在你的didFinishLaunching(或适合你需要的地方)你必须调用:
let app = UIApplication.sharedApplication()
let settings = UIUserNotificationSettings(forTypes: [.Alert, .Badge, .Sound], categories: nil)
app.registerUserNotificationSettings(settings)
app.registerForRemoteNotifications()
At this point, your users will be prompted with a typical Allow/Don't Allow prompt message. Regardless of your user's choice you will get a call to the method above, allowing for a fine grain configuration of your app. The result will be something like:
此时,系统将提示您的用户使用典型的“允许/不允许”提示消息。无论您的用户选择何种方式,您都可以调用上述方法,从而实现应用程序的细粒度配置。结果将是这样的:
Notification Status: <UIUserNotificationSettings: 0x7fa261701da0; types: (none);>
Notification Status: <UIUserNotificationSettings: 0x7ff032e21dd0; types: (UIUserNotificationTypeAlert UIUserNotificationTypeBadge UIUserNotificationTypeSound);>
In the first case, you will notice that the user denied the notifications. The second one is about the allow option.
在第一种情况下,您会注意到用户拒绝了通知。第二个是关于允许选项。
#1
5
Your didFailToRegisterForRemoteNotificationsWithError
method isn't called, because the registration didn't fail - it was never even attempted because the user denied the request.
您的didFailToRegisterForRemoteNotificationsWithError方法未被调用,因为注册没有失败 - 甚至从未尝试过,因为用户拒绝了请求。
On iOS7 you can do a couple of things:
在iOS7上,您可以做以下几件事:
- Assume that remote notifications aren't available until
didRegisterForRemoteNotificationsWithDeviceToken
is called - 假设在调用didRegisterForRemoteNotificationsWithDeviceToken之前,远程通知不可用
- Check the value
enabledRemoteNotificationTypes
on theUIApplication
object - 检查UIApplication对象上的值enabledRemoteNotificationTypes
#2
7
I was trying to find a way around this same issue.
我试图找到绕过同样问题的方法。
When the push notification permission UIAlert is shown, it is shown from outside of my app. Once the user has selected "Don't Allow" or "OK", my app is becoming active again.
当显示推送通知权限UIAlert时,它会从我的应用程序外部显示。一旦用户选择“不允许”或“确定”,我的应用程序将再次变为活动状态。
I have a view controller that I'm presenting before prompting the user for Push permissions. In this view controller I listen for the UIApplicationDidBecomeActiveNotification
, and then dismiss my view controller.
在提示用户输入推送权限之前,我有一个视图控制器。在这个视图控制器中,我监听UIApplicationDidBecomeActiveNotification,然后关闭我的视图控制器。
This has been working pretty well, whereas every other solution I've seen hasn't worked for me at all.
这一直很好用,而我见过的所有其他解决方案根本不适用于我。
#3
2
Assuming that you're compiling against iOS8 or newer, you can use the following delegate method:
假设您正在针对iOS8或更新版本进行编译,您可以使用以下委托方法:
func application(application: UIApplication, didRegisterUserNotificationSettings notificationSettings: UIUserNotificationSettings) {
print("Notifications status: \(notificationSettings)")
}
then on your didFinishLaunching (or where is appropriate for your needs) you must invoke:
然后在你的didFinishLaunching(或适合你需要的地方)你必须调用:
let app = UIApplication.sharedApplication()
let settings = UIUserNotificationSettings(forTypes: [.Alert, .Badge, .Sound], categories: nil)
app.registerUserNotificationSettings(settings)
app.registerForRemoteNotifications()
At this point, your users will be prompted with a typical Allow/Don't Allow prompt message. Regardless of your user's choice you will get a call to the method above, allowing for a fine grain configuration of your app. The result will be something like:
此时,系统将提示您的用户使用典型的“允许/不允许”提示消息。无论您的用户选择何种方式,您都可以调用上述方法,从而实现应用程序的细粒度配置。结果将是这样的:
Notification Status: <UIUserNotificationSettings: 0x7fa261701da0; types: (none);>
Notification Status: <UIUserNotificationSettings: 0x7ff032e21dd0; types: (UIUserNotificationTypeAlert UIUserNotificationTypeBadge UIUserNotificationTypeSound);>
In the first case, you will notice that the user denied the notifications. The second one is about the allow option.
在第一种情况下,您会注意到用户拒绝了通知。第二个是关于允许选项。