不久后,远程通知的后台任务暂停

Mar*_*les 3 push-notification ios background-task

我正在使用具有content-available:true标志的远程通知,以在无提示推送通知时在后台启动应用程序,并处理或从远程API获取更新。当应用程序处于前台状态或上次运行后处于挂起状态时,代码可以正常执行。

在后台测试期间,当系统根据传入的静默推送通知启动应用程序时,仅对代码进行了部分处理,并且在大约150毫秒后迅速将其挂起。我希望该应用程序将有30秒的时间来处理传入的通知及其有效负载。如果需要更多时间来处理和/或获取新数据,是否需要调整应用程序功能或请求后台任务?

部署目标iOS 8,在iOS 9上进行测试.Xcode 7.3.1,Swift 2.2.1。

功能:启用后台模式,模式:启用远程通知

AppDelegate

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

    if let userInfo = userInfo as? [String: AnyObject] {

        // Processing of the payload is done in separate Operation class (using Operations framework)
        // The completion handler is called on the end of the processing/fetching in that operation
        // But in case of launching the app in the background it never reaches the call of the completion handler

        let parseNotificationOperation = ParseNotificationOperation(userInfo: userInfo, fetchCompletionHandler: completionHandler)
        MainService.shared.enqueueApnsOperation(parseNotificationOperation)
    }
}
Run Code Online (Sandbox Code Playgroud)

San*_*ari 5

马丁·科尔斯

您可以利用expirationHandlers来延长后台执行时间。尽管iOS将为您的应用分配多少时间取决于我们无法控制的各种因素,但我们注意到,大多数情况下,它可以为我们的应用提供3分钟的后台运行时间。

这是您可以实现的方法:)

在您的AppDelegate中声明,

UIBackgroundTaskIdentifier backgroundTask;
Run Code Online (Sandbox Code Playgroud)

当您在didReceiveRemoteNotification中接收到APNS时,请写下此代码,

if (!backgroundTask || backgroundTask == UIBackgroundTaskInvalid) {
        backgroundTask = [[UIApplication sharedApplication] beginBackgroundTaskWithExpirationHandler:^{
                //do all clean up job here gets called few seconds before expiration
                [[UIApplication sharedApplication] endBackgroundTask:backgroundTask];
                backgroundTask = UIBackgroundTaskInvalid;
        }];
    }
Run Code Online (Sandbox Code Playgroud)

编辑

刚意识到您正在使用swift,所以这是swift中的代码:)

在AppDelegate中声明一个名为backgroundTask的变量,

var backgroundTask : UIBackgroundTaskIdentifier = UIBackgroundTaskInvalid
Run Code Online (Sandbox Code Playgroud)

并在如下的didRecieveRemoteNotification中使用它,

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

    if let userInfo = userInfo as? [String: AnyObject] {
        let parseNotificationOperation = ParseNotificationOperation(userInfo: userInfo, fetchCompletionHandler: completionHandler)
        MainService.shared.enqueueApnsOperation(parseNotificationOperation)

        if (backgroundTask == UIBackgroundTaskInvalid) {
            backgroundTask = UIApplication.sharedApplication().beginBackgroundTaskWithExpirationHandler { () -> Void in
                self.endTask()
            }
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

最后,编写完成后使失效处理程序无效的方法:)

func endTask(){
   //do all your clean up here, this is called few seconds before the task expires.
   UIApplication.sharedApplication().endBackgroundTask(backgroundTask)
   backgroundTask = UIBackgroundTaskInvalid;
}
Run Code Online (Sandbox Code Playgroud)

就是这样:)快乐的编码伙伴:)

  • @digs:抱歉,我还没有使用 iOS 13 的更改来更新自己,所以现在还不知道:| 如果我了解这方面的情况,我会及时通知您 (2认同)