Proper use of beginBackgroundTaskWithExpirationHandler

background-thread, ios, multitasking, network-programming, objective-c

Solution

If you want your network transaction to continue in the background, then you'll need to wrap it in a background task. It's also very important that you call `endBackgroundTask` when you're finished - otherwise the app will be killed after its allotted time has expired.

Mine tend look something like this:

- (void) doUpdate 
{
    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{

        [self beginBackgroundUpdateTask];

        NSURLResponse * response = nil;
        NSError  * error = nil;
        NSData * responseData = [NSURLConnection sendSynchronousRequest: request returningResponse: &response error: &error];

        // Do something with the result

        [self endBackgroundUpdateTask];
    });
}
- (void) beginBackgroundUpdateTask
{
    self.backgroundUpdateTask = [[UIApplication sharedApplication] beginBackgroundTaskWithExpirationHandler:^{
        [self endBackgroundUpdateTask];
    }];
}

- (void) endBackgroundUpdateTask
{
    [[UIApplication sharedApplication] endBackgroundTask: self.backgroundUpdateTask];
    self.backgroundUpdateTask = UIBackgroundTaskInvalid;
}

I have a `UIBackgroundTaskIdentifier` property for each background task

Equivalent code in Swift

func doUpdate () {

    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), {

        let taskID = beginBackgroundUpdateTask()

        var response: URLResponse?, error: NSError?, request: NSURLRequest?

        let data = NSURLConnection.sendSynchronousRequest(request, returningResponse: &response, error: &error)

        // Do something with the result

        endBackgroundUpdateTask(taskID)

        })
}

func beginBackgroundUpdateTask() -> UIBackgroundTaskIdentifier {
    return UIApplication.shared.beginBackgroundTask(expirationHandler: ({}))
}

func endBackgroundUpdateTask(taskID: UIBackgroundTaskIdentifier) {
    UIApplication.shared.endBackgroundTask(taskID)
}

Problem

I'm a bit confused about how and when to use `beginBackgroundTaskWithExpirationHandler`. Apple shows in their examples to use it in `applicationDidEnterBackground` delegate, to get more time to complete some important task, usually a network transaction. When looking on my app, it seems like most of my network stuff is important, and when one is started I would like to complete it if the user pressed the home button. So is it accepted/good practice to wrap every network transaction (and I'm not talking about downloading big chunk of data, it mostly some short xml) with `beginBackgroundTaskWithExpirationHandler` to be on the safe side?

Original source

Related problems