为什么当我的应用程序在前台时,didReceiveRemoteNotification未被调用,但是didReceiveRemoteNotification:fetchCompletionHandler被调用?

13

如果我覆盖

override func application(application: UIApplication, didReceiveRemoteNotification userInfo: [NSObject : AnyObject], fetchCompletionHandler completionHandler: (UIBackgroundFetchResult) -> Void) {
    println("hey)
}

当我发送推送通知时,我成功地在应用程序前台调用了该方法。

如果我重写

override func application(application: UIApplication, didReceiveRemoteNotification userInfo: [NSObject : AnyObject]) {
    println("hey")
}

当我在前台使用应用程序发送通知时,我的方法没有接收到任何调用。为什么第一个可以工作,但是当应用程序在前台时第二个就不行了?需要注意的是,我每次只实现其中一个而不是同时实现两个。

2个回答

15

除非您需要支持 iOS<7(当时引入),否则应使用回调版本。因为您正在使用 Swift,所以我认为这不是问题。

较旧的方法可以追溯到 iOS3,并且已经被弃用了:

尽可能实现application:didReceiveRemoteNotification:fetchCompletionHandler:方法而不是此方法。如果委托实现了两种方法,则app对象将调用application:didReceiveRemoteNotification:fetchCompletionHandler:方法。

老版本还会根据应用程序是在线(前台或后台)还是从冷启动启动而产生不同的结果。在后一种情况下,它将不会被调用,您需要在didFinishLaunchingWithOptions上拦截launchOptions字典以获取infoDict:

如果应用程序在远程通知到达时未运行,则该方法将启动应用程序并在启动选项字典中提供适当的信息。该应用程序不会调用此方法来处理该远程通知。

请使用回调版本。它适用于所有情况。您不必使用完成处理程序/块,在这种情况下效果相同(与较新的方法更一致)。

更新

抱歉,Apple表示您必须“尽快”调用完成块-在操作系统放弃之前,您有30秒的时间。这可能是您警告的来源。

一旦完成通知处理,您必须调用处理程序参数中的块,否则将终止您的应用程序。您的应用程序最多有30秒的墙时钟时间来处理通知并调用指定的完成处理程序块。实际上,您应该尽快调用处理程序块。

因此,请调用完成块:

        completionHandler(UIBackgroundFetchResult.NoData)

我一直在使用这种方法而没有调用完成块,并且没有遇到任何问题,但为了安全起见,现在我会添加一个。苹果建议如果您不这样做,您的应用程序将无法获得前台,但我在实践中没有看到过这种情况。


当我不使用完成处理程序时,会收到警告。我应该忽略它吗? - Adam Johns
@AdamJohns - 你收到了什么警告?使用的是哪个版本的XCode/Swift? - foundry

0
你是否至少使用UIApplication:registerUserNotificationSettings:注册了一个UIUserNotificationType
如果你没有注册badge、sound或alert,那么你只能接收静默通知,这些通知只能通过FetchCompletionHandler传递。

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