How to use beginBackgroundTaskWithExpirationHandler for already running task in iOS How to use beginBackgroundTaskWithExpirationHandler for already running task in iOS ios ios

How to use beginBackgroundTaskWithExpirationHandler for already running task in iOS


Despite its name, beginBackgroundTaskWithExpirationHandler: does not actually "begin" a task. It might be better thought of as "register..." rather than "begin...." You're just telling the system that you're in the middle of doing something that would like to complete if that's ok.

Several points:

  • In almost all cases, you want to call beginBackgroundTaskWithExpirationHandler: when you start doing the thing you want to do, and then endBackgroundTask: when you're done. You almost never call these at the point that the user presses the Home button (unless that's the point when you start the task, such as saving something to the server).

  • You can have as many "background tasks" as you want open at a time. They cost nothing. They're like retain counts. As long as you still have one open (a "begin" that did not get to its "end"), then the system will consider that a request for more time. There is very little cost to calling the "begin" and "end" methods, so use these to bracket anything that you want extra time to finish.

  • There is no way to be certain that you will get to finish your sync. These methods just make a request. The OS may still deny that request. The OS may still kill you anytime it needs some extra resources. The OS is not infinitely patient; if you take too long (about 10 minutes usually), it'll kill you anyway after calling your expiration handler. The OS may kill you because the phone is being turned off. Your app must be able to deal with not getting to finish. The OS just gives you this ability so that you can improve the user experience.


I used below code for background task handler:

__block UIBackgroundTaskIdentifier backgroundTaskIdentifier = [[UIApplication sharedApplication] beginBackgroundTaskWithExpirationHandler:^{    NSLog(@"Background Time:%f",[[UIApplication sharedApplication] backgroundTimeRemaining]);    [[UIApplication sharedApplication] endBackgroundTask:backgroundTaskIdentifier];    backgroundTaskIdentifier = UIBackgroundTaskInvalid;}];


Here's how I used beginBackgroundTaskWithExpirationHandler, including the call to the method to be done in the background. This includes code for starting the new async task. So not exactly what is asked in the question. Adding code below, thinking someone might be looking for this scenario:

- (void)didReceiveObjList:(CFDataRef)message{  // Received Object List. Processing the list can take a few seconds.  // So doing it in separate thread with expiration handler to ensure it gets some time to do     the task even if the app goes to background.  UIApplication *application = [UIApplication sharedApplication];  __block UIBackgroundTaskIdentifier bgTask = [application beginBackgroundTaskWithExpirationHandler:^{    [application endBackgroundTask:bgTask];    bgTask = UIBackgroundTaskInvalid;}];  dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{      [self processObjList:message];    [application endBackgroundTask:bgTask];    bgTask = UIBackgroundTaskInvalid;  });  NSLog(@"Main Thread proceeding...");}