未正确调用 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 方法的主要内容,如果未能解决你的问题,请参考以下文章

未正确调用 registerForRemoteNotifications 方法

由于 Angular 中的服务调用延迟,数组未正确更新

wcf 调用完成事件未按正确顺序触发

jni报错日志打印方法未定义

sysinfo 系统调用未返回正确的 freeram 值

使用 open 系统调用未正确设置文件权限