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
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.