iOS background fetch time limit crash

本秂侑毒 提交于 2019-12-04 12:46:08

Every background fetch has a time limit, which is I believe 30 seconds. Unlike a normal background task that can utilize an expiration handler to automatically clean up and do what you need to do when you run out of time, background fetches currently don't have that ability. One way you can handle this is perhaps start an NSTimer that is scheduled to go off something like 20-25 seconds into your background fetch, and have that timer call a function that handles if you haven't completed your background task to stop whatever you're doing and clean up everything so the app can go back to being backgrounded normally. From the docs:

When this method is called, your app has up to 30 seconds of wall-clock time to perform the download operation and call the specified completion handler block. In practice, your app should call the completion handler block as soon as possible after downloading the needed data. If you do not call the completion handler in time, your app is terminated.

https://developer.apple.com/library/ios/documentation/uikit/reference/uiapplicationdelegate_protocol/Reference/Reference.html#//apple_ref/occ/intfm/UIApplicationDelegate/application:performFetchWithCompletionHandler:

The bold part sounds like that's exactly what's happening. Either way, you need to get done what you're trying to get done within the 30 seconds, otherwise you need to cancel it or your app will be terminated.

This question is kind of old but maybe the following code can help some developers that are interested in a code snippet based on Mike´s answer. As Mike suggested I also use a NSTimer to cancel the background fetch when it takes too much time. In my background fetch I access my webservice with AFNetworking to grab some new data. If the time (I chose 25 seconds) is up I simply cancel all my open requests to the webservice in the NSOperationQueue. Here´s my code:

func application(application: UIApplication, performFetchWithCompletionHandler completionHandler: (UIBackgroundFetchResult) -> Void) {

    // This Handler accesses my webservice using AFNetworking and creates NSOperationQueue to enqueue the requests
    backgroundSearchHandler = BackgroundFetchSearchHandler()

    let cancelTimer = NSTimer.scheduledTimerWithTimeInterval(25, target: self, selector: "cancelBackgroundFetch", userInfo: nil, repeats: false)

    backgroundSearchHandler!.findNewResultsForSavedSearches { (completed, newResultCount) -> Void in

        // This block is also called when the timer is over and the requests were cancelled

        // Stop the timer
        cancelTimer.invalidate()

        if !completed
        {
            completionHandler(.Failed)
            return
        }

        if newResultCount <= 0
        {
            completionHandler(.NoData)
            return
        }

        completionHandler(.NewData)
    }
}

func cancelBackgroundFetch()
{
    backgroundSearchHandler?.cancel()
    // This is calling cancelAllOperations() on the NSOperationQueue in my background search handler
}

Hope this helps!

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!