I have some long running process which I want to run even if application goes in background. I am calling application's beginBackgroundTaskWithExpirationHandler:
method and in the expirationBlock I am calling application's endBackgroundTask
.
Here is the implementation:
__block UIBackgroundTaskIdentifier task = [[UIApplication sharedApplication] beginBackgroundTaskWithExpirationHandler:^{
[[UIApplication sharedApplication] endBackgroundTask:task];
task = UIBackgroundTaskInvalid;
}];
dispatch_queue_t queue = dispatch_queue_create("com.test.test1234", DISPATCH_QUEUE_SERIAL);
dispatch_async(queue, ^{
// My Task goes here
});
In some cases, my serial queue have more task to perform which can not be completed within the time provided by system. So expiration block will execute and in that I am ending the UIBackgroundTaskIdentifier
but not stopping the dispatch process (I can't even cancel a dispatch).
Apple's document says:
Each call to the beginBackgroundTaskWithName:expirationHandler: or beginBackgroundTaskWithExpirationHandler: method generates a unique token to associate with the corresponding task. When your app completes a task, it must call the endBackgroundTask: method with the corresponding token to let the system know that the task is complete. Failure to call the endBackgroundTask: method for a background task will result in the termination of your app. If you provided an expiration handler when starting the task, the system calls that handler and gives you one last chance to end the task and avoid termination.
So, according to this if I doesn't call the endBackgroundTask:
my app will be terminated, which is ok.
My question is: with my current implementation what if I call endBackgroundTask:
in expirationHandler block and my dispatch queue's task doesn't get complete? My app will be terminated or will be suspended?
thanks
Here are some scenario, which you need to handle while using beginBackgroundTaskWithExpirationHandler
otherwise your app will terminate
.
Scenario 1 : Your app is running in Foreground
. you are start beginBackgroundTaskWithExpirationHandler
then enter in Background
mode. your app keep alive for long.
Scenario 2 : Your app is running in Foreground
. you are start beginBackgroundTaskWithExpirationHandler
then enter in Background
mode. Then come back to Foreground
mode and you are not calling endBackgroundTask
then your application still execute background queue
so it will extent that process for next 3 minute
(After IOS 7 introduce. before IOS 7, the process execution time was 10 minute). so you must need to cancel background queue and task come out from background queue and enter in foreground queue.
So here are the code that show you. what is best way handle background process.
Step 1: Declare __block UIBackgroundTaskIdentifier bgTask as global variable.
Step 2: To add following code in applicationDidEnterBackground.
- (void)applicationDidEnterBackground:(UIApplication *)application {
bgTask = [application beginBackgroundTaskWithExpirationHandler:^{
bgTask = UIBackgroundTaskInvalid;
}];
}
Step 3: Stop background task handler once apps come in foreground mode.
- (void)applicationWillEnterForeground:(UIApplication *)application {
// Called as part of the transition from the background to the active state; here you can undo many of the changes made on entering the background.
[[UIApplication sharedApplication] endBackgroundTask:bgTask];
}
If you don't call endBackgroundTask
in your expiration handler, your app will be terminated.
Once you call endBackgroundTask
in your expiration handler, you are only telling the OS "OK, I'm done with saving critical tasks. It's up to you now." After that your app may be suspended for a while and terminated later, or it may be terminated immediately depending on the system resources.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With