Search code examples
iosbackgroundcore-locationcllocationmanagerforeground

Location-aware iOS app with background support design issue


I have location services enabled for updating locations when app in background, and I also listen for location updates when app in foreground, displaying a map. What should be the best way to design this scenario in iOS? I've thought about some options:

1) Having an instance of a class with a locationManager member that is its delegate itself. Then, in the body of the didUpdateToLocation delegate method, something like:

- (void)locationManager:(CLLocationManager *)manager didUpdateToLocation:(CLLocation *)newLocation fromLocation:(CLLocation *)oldLocation
{
   if (!background) {
      // Perform some processing and notify the view controller which displays the map
      // by means of Notification Center
   }
   else {
      appDelegate.bgTask = [[UIApplication sharedApplication] beginBackgroundTaskWithExpirationHandler:^{
         [[UIApplication sharedApplication] endBackgroundTask:appDelegate.bgTask];
         appDelegate.bgTask = UIBackgroundTaskInvalid;
      }];

      dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
         // Perform some data processing 

         // Close background task
         if (appDelegate.bgTask != UIBackgroundTaskInvalid) {
            [[UIApplication sharedApplication] endBackgroundTask:appDelegate.bgTask];
            appDelegate.bgTask = UIBackgroundTaskInvalid;
         }
      });
   }
}

(Note: I'm not sure if having location services enabled as background service, it is needed to perform the processing of locations as if it were a finite background task...). The instance of such class could be a member of AppDelegate, and start listening for locations when entering background or calling the instance from the viewModel displaying the map. So, AppDelegate would have a reference to the instance managing the locationManager, and the map viewController would have a reference to AppDelegate, or communicate also by means of Notification Center.

2) Having the locationManager member directly in AppDelegate, and being the delegate itself.

Would it be better to encapsulate de locations listening and management in a different class, or handle it directly in AppDelegate? Having into account that I have to be able to listen for locations and perform some tasks both in foreground and in background.

Thanks in advance


Solution

  • I think your best strategy is to have a singleton instance of a class that is a locationManager delegate. This instance would be responsible to filter whatever comes back from locationManager and ultimately assigns the location to one of its properties, let's call it myLoc.

    This solves your centralized logic issues where the location needs post-processing after being acquired.

    Second, in order to get the correct UIViewControllers and other class instances to do what they need when the location is updated, I suggest you use Key-Value Observing (KVO) on myLoc. I assume you know how that works. The reason I suggest KVO is that you need to trigger changes in multiple areas of the code based on the location being changed, and KVO is made for that kind of pattern.