为什么当我的应用程序在前台时,没有调用 didReceiveRemoteNotification 而是调用 didReceiveRemoteNotification:fetchCompletionHandler?

Why is didReceiveRemoteNotification not called but didReceiveRemoteNotification:fetchCompletionHandler called when my app is in the foreground?

如果我覆盖

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")
}

当应用程序在前台发送通知时,我没有收到任何对该方法的调用。为什么当应用程序在前台时第一个有效,但第二个无效?

请注意,我一次只实施其中一个。不能同时。

您是否至少注册了一个 UIUserNotificationType UIApplication:registerUserNotificationSettings:

如果您不注册徽章、声音或警报,那么您只能接收静默通知,这些通知仅通过 FetchCompletionHandler 传送。

您应该使用回调版本,除非您需要支持 ios<7(引入时)。当您使用 Swift 时,我预计情况并非如此。

旧方法可追溯到 ios3,除名称外均已弃用:

Implement the application:didReceiveRemoteNotification:fetchCompletionHandler: method instead of this one whenever possible. If your delegate implements both methods, the app object calls the application:didReceiveRemoteNotification:fetchCompletionHandler: method.

旧版本也会根据应用程序是实时(前台或后台)还是从冷启动启动而给出不同的结果。在后一种情况下,它不会被调用,您需要拦截 didFinishLaunchingWithOptions 上的 launchOptions dict 以获取 infoDict:

If the app is not running when a remote notification arrives, the method launches the app and provides the appropriate information in the launch options dictionary. The app does not call this method to handle that remote notification.

使用回调版本。它适用于所有情况。 你不必使用补全handler/block,那样效果是一样的(嗯,更符合新方法)。

更新

抱歉,Apple 说你 do 必须调用完成块 "as soon as possible" - 在 OS 放弃之前你有 30 秒的时间这样做你。这可能是您发出警告的来源。

As soon as you finish processing the notification, you must call the block in the handler parameter or your app will be terminated. Your app has up to 30 seconds of wall-clock time to process the notification and call the specified completion handler block. In practice, you should call the handler block as soon as you are done processing the notification.

所以调用完成块:

        completionHandler(UIBackgroundFetchResult.NoData)

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