Dispatched Saving operations on applicationDidEnterBackground:
Asked Answered
S

2

4

Apple's documentation of "App States and Multitasking" (Section "What to Do When Moving to the Background") say for saving when the app goes to background:

Save user data and app state information. All unsaved changes should be written to disk when entering the background. This step is necessary because your app might be quietly killed while in the background for any number of reasons. You can perform this operation from a background thread as needed.

When I start a dispatched operation e.g. for saving which takes some time at applicationDidEnterBackground: like the following I don't get the NSLog output when pressing the home button. After returning to the app, the NSLog output appears.

- (void)applicationDidEnterBackground:(UIApplication *)application {
      dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
         [self performOperation];
         NSLog(@"Operation finished");
      });
}

Can I be sure that the performOperation method was performed completely or did it interrupt when the app entered sleep mode?

Sirenasirenic answered 4/3, 2013 at 22:50 Comment(0)
M
6

Make sure that you have the plist key setting UIApplicationExitsOnSuspend set to no to ensure applicationDidEnterBackground is called.

Next make sure you start a long running task. In your case it would look like this:

- (void)applicationDidEnterBackground:(UIApplication *)application {
   UIBackgroundTaskIdentifier __block bgTask = nil;
   UIApplication  *app = [UIApplication sharedApplication];
   bgTask = [app beginBackgroundTaskWithExpirationHandler:^{ 
         [app endBackgroundTask:bgTask]; 
         bgTask = UIBackgroundTaskInvalid;
    }];
    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
         [self performOperation];
         NSLog(@"Operation finished");
     });
 }

That way you have told the app to hang around for 10 minutes while you finish up. At the end of ten minutes the expiration handler is called.

In addition you can set the required background mode keys to get more time. There are a number of hacks and variations on this that can get you more time using the stuff I mentioned above.

Marabou answered 4/3, 2013 at 23:2 Comment(2)
Thanks for you code example. I have some more questions: 1. Is UIApplicationExitsOnSuspend needed? I didn't set it and applicationDidEnterBackground: is called. 2. Shouldn't bgTask be declared as a block variable and in the dispatching block after [self performOperation] also be called [app endBackgroundTask:bgTask]; bgTask = UIBackgroundTaskInvalid;? 3. What happens when the user taps the app again before the operation is completed or before the background task is ended?Sirenasirenic
1. UIApplicationExitsOnSuspend is not needed unless you wish to change the default behaviour, I just was making sure you were aware of it/didnt have it set differently w/o knowing etc... 2. You are correct, bgTask should be a block variable I made the edit. 3. If the user enters the foreground the scheduled expiration handler is never called because the backgroundtask did not expire. ApplicationDidEnterForeground is called instead. Your operation being performed on the dispatch queue is not affected as the app has remained active during all of this, it will carry on as desired.Marabou
D
0

i will use a different kind of logging just to be sure:

Flexible iOS Logging

By adding this logging to your project you can check the logs of your project regardless if you are debugging or not by going to Organizer -> Devices -> "Your device" -> console.

I think this is the best way and it has helped me a lot when i am not sure if i can debug something.

Dowling answered 4/3, 2013 at 23:6 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.