未正确调用 registerForRemoteNotifications 方法
Posted
技术标签:
【中文标题】未正确调用 registerForRemoteNotifications 方法【英文标题】:registerForRemoteNotifications method not being called properly 【发布时间】:2014-06-30 08:16:29 【问题描述】:我目前正在使用 Xcode6 beta(第一个版本)。使用 parse.com,我正在尝试实现推送通知。在我的应用委托中,我有
[application registerForRemoteNotifications];
当我在我的 ios8 beta iPhone 上运行它时,该应用程序不会询问我是否要启用推送通知,并且相应的 application:didRegisterForRemoteNotificationsWithDeviceToken:
永远不会被调用。但是,当我尝试在 ios7 iPhone 上运行它时,应用程序崩溃了,我收到了 registerForRemoteNotifications
方法的 unrecognized selector
错误。
然后,我尝试在以前版本的 Xcode(5.0 版)上运行它,但收到编译错误 no visible @interface declares registerForRemoteNotifications
我假设此错误与过渡到 iOS 8 的错误有关,但我不确定如何解决此问题。
【问题讨论】:
【参考方案1】:阅读 UIApplication.h 中的代码。
你会知道怎么做的。
第一:
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
添加这样的代码
#ifdef __IPHONE_8_0
//Right, that is the point
UIUserNotificationSettings *settings = [UIUserNotificationSettings settingsForTypes:(UIUserNotificationTypeAlert | UIUserNotificationTypeBadge | UIUserNotificationTypeSound) categories:nil];
[[UIApplication sharedApplication] registerUserNotificationSettings:settings];
#else
//register to receive notifications
UIRemoteNotificationType myTypes = UIRemoteNotificationTypeBadge | UIRemoteNotificationTypeAlert | UIRemoteNotificationTypeSound;
[[UIApplication sharedApplication] registerForRemoteNotificationTypes:myTypes];
#endif
第二:
添加此功能
#ifdef __IPHONE_8_0
- (void)application:(UIApplication *)application didRegisterUserNotificationSettings:(UIUserNotificationSettings *)notificationSettings
//register to receive notifications
[application registerForRemoteNotifications];
- (void)application:(UIApplication *)application handleActionWithIdentifier:(NSString *)identifier forRemoteNotification:(NSDictionary *)userInfo completionHandler:(void(^)())completionHandler
//handle the actions
if ([identifier isEqualToString:@"declineAction"])
else if ([identifier isEqualToString:@"answerAction"])
#endif
你可以得到 deviceToken in
- (void)application:(UIApplication *)application didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)deviceToken
如果还是不行,使用这个函数并 NSLog error
-(void)application:(UIApplication *)application didFailToRegisterForRemoteNotificationsWithError:(NSError *)error
【讨论】:
这个答案,你也在这里逐字发布:***.com/a/24488562/1146823,没有正确实现运行时检查你是否在 iOS 8 上运行。对于那些需要同时支持 iOS 7 和 8,值得点击其他答案并阅读那里的 cmets 以获得实现运行时检查的正确方法。 这实际上是不正确的,应该被否决。 application:didRegisterUserNotificationSettings: 方法不会被调用直到你调用 UIApplication registerForRemoteNotification 方法。你不会在那个方法中调用它。 @GregG 我不知道是什么让你这么说。文档特别说:“注意:只有当应用程序已成功注册用户通知时,才会进行这些回调 registerUserNotificationSettings:” 文档指出每次应用启动时都应调用 registerForRemoteNotifications 以确保获得更新的令牌。最新的 Remote Notifications PG (10/31/14) 声明 didRegisterUserNotificationSettings 只会在用户响应警报时被调用一次,因此在该回调中调用 registerForRemoteNotifications 将导致它每次都被调用一次。此外,最新的文档显示了一个示例,其中 registerUserNotificationSettings: 和 registerForRemoteNotifications 在 didFinishLaunchingWithOptions: 中按顺序调用 请原谅:我误读了有关 didRegisterUserNotificationSettings 回调的文档。每次都会调用它,但警报只显示一次。因此,应该可以将 registerForRemoteNotifcations 调用放在那里,尽管文档中的示例正如我之前在 didFinishLaunchingWithOptions: 方法中所述。【参考方案2】:几个观察:
问题是使用 REMOTE,而不是本地 有些问题涉及本地,那是完全不同的事情 我同意回答时间可能很长,但您必须实现回调(也称为委托方法),正如其他人指出的那样 不要针对编译器标志进行测试,在概念上和实际上都是错误的在此代码中测试选择器的存在:
func registerForPushForiOS7AndAbove()
UIApplication.sharedApplication()
let application = UIApplication.sharedApplication()
if application.respondsToSelector(Selector("registerUserNotificationSettings:"))
let notifSettings = UIUserNotificationSettings(forTypes: .Sound | .Alert | .Badge,
categories: nil)
application.registerUserNotificationSettings(notifSettings)
application.registerForRemoteNotifications()
else
application.registerForRemoteNotificationTypes( .Sound | .Alert | .Badge )
(不要错过 PList中的UIBackgroundModes..可以在Capabilities中完成)
【讨论】:
我想和你生孩子!【参考方案3】:在 iOS 8 中,系统不会要求用户允许您的应用发送推送(远程)通知,默认情况下是允许的。
用户可以在Settings > Yor App > Notifications > Allow Notifications上选择不允许来自您应用的通知。
【讨论】:
当我将我的 iPhone 4S 从 7.1.2 更新到 8.0.2 时,推送停止工作,而它在我的 iPhone 5 8.0.2 上就像一个魅力一样工作。我必须在“设置”>“你的应用”路径中选择“后台更新”行才能让它工作。 在某些 iOS 版本中需要 registerForRemoteNotifications() 在其他版本中不需要。我通过检查 SharedApplication 是否响应选择器“registerForRemoteNotifications:”解决了这个问题。如果确实如此,那么我就打电话给它。【参考方案4】:只需使用这段 sn-p 代码在 iOS 8 中注册通知:
UIUserNotificationSettings *settings =
[UIUserNotificationSettings
settingsForTypes: (UIUserNotificationTypeBadge |
UIUserNotificationTypeSound |
UIUserNotificationTypeAlert)
categories:nil];
[[UIApplication sharedApplication] registerUserNotificationSettings:settings];
使用UIUserNotificationType
而不是UIRemoteNotificationType
!
【讨论】:
这很好用并且没有弃用警告,这是这个问题的公认答案。【参考方案5】:registerForRemoteNotifications
方法在 iOS8 中可用。
application:didRegisterForRemoteNotificationsWithDeviceToken:
委托方法只有在注册成功时才会被调用,如果失败则会调用application:didFailToRegisterForRemoteNotificationsWithError:
方法。
欲了解更多信息,请通过:UIApplication Class reference
同时检查通知是否为应用Settings -> Notifications -> YourApp -> Enable_Notifications
启用
根据文档,这两个回调都不会发生 直到设备与推送服务器建立持久连接。所以 如果没有可用的 wifi 或数据连接,回调将不会 发生 - 苹果不认为这是一个错误情况。只有可能导致 didFail 的错误... 回调是不正确的证书/应用权限问题(a 开发问题),或用户拒绝许可。
请转至Push notification programming guide
【讨论】:
我实现了两个委托方法,但都没有调用 @Mahir 检查互联网连接是否可用。 事实上,对于 ios8 设备而言,互联网速度异常缓慢。由于registerForRemoteNotifications
只有ios8,要试用ios7设备,我用registerForRemoteNotificationTypes:
吗?
@Mahir 一直建议使用新的api,检查操作系统版本调用具体方法。
在 iOS9 上测试,didRegisterForRemoteNotificationsWithDeviceToken
即使没有互联网连接也会被调用。但是需要在线调用一次才能让操作系统存储token。以上是关于未正确调用 registerForRemoteNotifications 方法的主要内容,如果未能解决你的问题,请参考以下文章