I have an iOS app that uses location services to track users. It is a game app so precise location is needed whenever available. The UI is in react native but all the location handling code, and AppDelegate, are all written in objective C. I am able to get location updates through locationManager and the didUpdateLocations delegate method perfectly fine when the app is in foreground or background. By foreground I mean the app is visible on the screen, and by background I mean that the user has pressed the home button to stop using the app at the moment. In my location tracking in foreground and background, I have also called startMonitoringSignificantLocationChanges in addition to startUpdatingLocation. As I said, all this works fine in foreground and background.
But my understanding is that if the app is terminated, iOS is supposed to wake up an app like this if a significant location change occurs. In that case, the AppDelegate is supposed to check for the cause of the wakeup (using launchOptions, then call startMonitoringSignificantLocationChanges again and get the location through the didUpdateLocations delegate. This is NOT happening in my app after I have swiped up to kill the app. Even when I swipe up to kill the app and then drive a couple of miles away, the app does not wake up. The AppDelegate didFinishLaunchingWithOptions method is never called. My app just stays terminated.
How can I make my app wake up for a location change after I have swiped up to kill it? I thought startMonitoringSignificantLocationChanges was supposed to do this but it isn't doing it.
Here is my method to create the location manager:
- (void)createLocationManager { if (!self.locationManager) { // location manager not created yet so create it NSLog(@"Creating locationManager"); self.locationManager = [[CLLocationManager alloc] init]; self.locationManager.delegate = self; self.locationManager.desiredAccuracy = self.desiredLocationAccuracy; self.locationManager.allowsBackgroundLocationUpdates = YES; self.locationManager.pausesLocationUpdatesAutomatically = NO; if (self.locationManager.delegate == self) { NSLog(@"locationManager delegate set properly"); } if (self.locationManager.desiredAccuracy == DEFAULT_LOCATION_ACCURACY) { NSLog(@"locationManager accuracy set to best for navigation"); } }}
Here is how I start watching for location updates:
- (void)watchPosition:(void (^)(CLLocation *))positionChangedCallback { [self.locationManager startUpdatingLocation]; [self.locationManager startMonitoringSignificantLocationChanges];}
Note that I call startMonitoringSignificantLocationChanges. Here is AppDelegate didFinishLaunchingWithOptions:
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions{ // Upload messageto firebase saying we just launched or woke up the app [FIRApp configure]; FIRDatabaseReference *dbRef = [[FIRDatabase database] reference]; [self uploadToFirebase:dbRef Node:@"myapp/launch" Data:@"didFinishLaunchingWithOptions"]; if ([launchOptions objectForKey:UIApplicationLaunchOptionsLocationKey]) { [self uploadToFirebase:dbRef Node:@"myapp/launch" Data:@"woke from location change"]; [self createLocationManager]; [self watchPosition]; } ...