I'm building an application that checks if the user is near a store of my client, if it does, it sends him a notification.
I want the app to check it in the background as well.
I've added this lines to my info.plist
file:
and here is my code:
AppDelegate.m:
-(BOOL)application:(UIApplication *)application willFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
[self configureLocationManager];
[self.locationManager startUpdatingLocation];
return YES;
}
-(void)configureLocationManager
{
//Initializing locationManager
self.locationManager=[[CLLocationManager alloc] init];
//setting "locationManager"'s(CLLocationManager) delegate to "self"
self.locationManager.delegate=self.monitorLocationVC;
//Setting "locationManager"'s(CLLocationManager)'s distance filter to none
//self.locationManager.distanceFilter=kCLDistanceFilterNone;
//Setting "locationManager"'s(CLLocationManager)'s activityType to navigation
self.locationManager.activityType=CLActivityTypeAutomotiveNavigation;
//setting "locationManager"'s(CLLocationManager) desiredAccuracy to "best"
self.locationManager.desiredAccuracy=kCLLocationAccuracyBestForNavigation;
//If OS version is 9 or above - setting "allowsBackgroundLocationUpdates" to YES
if ([[[UIDevice currentDevice] systemVersion] floatValue] >= 9) {
self.locationManager.allowsBackgroundLocationUpdates = YES;
}
}
MonitorLocationViewController.m:
-(void)locationManager:(CLLocationManager *)manager didUpdateLocations:(NSArray<CLLocation *> *)locations
{
[self checkIfNearStore]; //Not being called in background
}
-(void)checkIfNearStore
{
for (Store *currentStore in self.allStores) {
if ([currentStore.circularRegion containsCoordinate:self.locationManager.location.coordinate]&¤tStore.alreadySendNotification==NO) {
NSLog(@"Entered: %@",[[self storeForRegion:currentStore.circularRegion] address]);
currentStore.alreadySendNotification=YES;
[self.storesAlreadySentNotifications addObject:currentStore];
}
}
for (Store *currentStore in self.storesAlreadySentNotifications) {
if (![currentStore.circularRegion containsCoordinate:self.locationManager.location.coordinate]) {
currentStore.alreadySendNotification=NO;
}
}
}
Anybody have an idea? Thanks!
Unfortunately, I can't post the code I use for geofencing due to NDA, but this article could help you achieve what you want: https://corgitoergosum.net/2013/01/12/geo-fencing-in-timetraveler-v2-part-i-of-3/
Background Location Updates
I recommend you give a close re-read of the discussion related to the startMonitoringSignificantLocationChanges method (You must use this method to resolve the issue). Note that you can force new updates by calling stopMonitoringSignificantLocationChanges and then calling the start... method again. You'll also need to monitor the timestamps in your locationManager:didUpdateLocations method.
Apple details the steps that you need to get the updates when the app is in the background. Basically you will have to intercept a key in your app delegate method. This SO question has Sample CODE.
But before you jump to the code, please review the discussion as recommended since it will give you a much clearer idea of how to master this behavior. As always you will also always want to monitor the failure delegate method mentioned in the discussion.
Apple Documentation
Nota Bene
Apple has posted this very important note on limitations for how often location updates are sent to the device. For battery conservation they try to limit the number of updates until the device moves 500 meters. Your testing should consider these limits.
Resources
For more complementary info please note the following answers to these SO questions:
#1 #2