We are currently developing an iOS application that needs to be checked in the background. At first we tried to use significant changes in location, but they are not accurate enough / do not work often enough. We examined the use of regional monitoring, but from what I read on the Internet, this is also not always accurate, and you also have the problem of a limited number of regions for monitoring. (We can ultimately try monitoring the region.) Right now, we are trying to use standard location updates to track a user's location in the background, with a plan to have them while checking at intervals of 5 minutes or so.
The application is registered for location updates in the background (using the "Application updates registers for location updates" for "Required background modes"), and we run a background task that checks the location once, stops location updates, and then uses NSThread sleepForTimeInterval: to (on At the moment, while we are in development) we suspend the task for 10 seconds. Then it checks the location again, stops location updates, pauses for 10 seconds, etc.
It looks like it works as expected ... When the application goes into the background, we get a log / notification with our location update every 10 seconds, and when the application opens again, the logs / notifications stop. However, the problem is that when the application goes back to the background a second time, it seems that the original background task has never been canceled and a new one is being created, so now two tasks are being performed, each of which checks the location for 10 seconds at intervals. If the application is open or sent to the background several times, then for each of them a background task is launched.
I thought about setting a flag to say โwas the application sent to the background at least once?โ And only run the task if it was first sent to the background, but this seems to cause additional problems , and (as a relatively new iOS developer) I am curious why background tasks are not canceled when the application comes to the fore.
The file AppDelegate.h contains ...
@interface AppDelegate : UIResponder <UIApplicationDelegate, CLLocationManagerDelegate> { UIWindow *window; UINavigationController *navigationController; UIBackgroundTaskIdentifier bgTask; BOOL inBackground; }
The file AppDelegate.m contains ...
- (void)applicationDidEnterBackground:(UIApplication *)application { inBackground = YES; bgTask = [[UIApplication sharedApplication] beginBackgroundTaskWithExpirationHandler:^{ [[UIApplication sharedApplication] endBackgroundTask:bgTask]; bgTask = UIBackgroundTaskInvalid; }]; dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ while (inBackground == YES) { NSLog(@"%@", @"Check location..."); [locationManager startUpdatingLocation]; [NSThread sleepForTimeInterval:10]; } [[UIApplication sharedApplication] endBackgroundTask:bgTask]; bgTask = UIBackgroundTaskInvalid; }); } - (void)applicationWillEnterForeground:(UIApplication *)application {
Location updates work as expected, I just canโt understand why the background tasks are not canceled / terminated when the application comes to the fore. I really wonder if this is not related to NSThread sleepForTimeInterval: but I'm not sure if this is the case, or how to fix it (if that is true). Thanks for any help!