I am trying to set up a small geofence (100 meters) to alert the user when they leave their home. To do this, I request the current location of users like this:
- (void)requestUsersCurrentLocation { if (self.locationManager == nil) self.locationManager = [[CLLocationManager alloc] init]; self.locationManager.delegate = self; self.locationManager.desiredAccuracy = kCLLocationAccuracyBest; self.locationManager.distanceFilter = 100; [self.locationManager startUpdatingLocation]; }
Using the delegation methods of CLLocationManager, I check if the application was able to determine the current location of users. In my testing, this works correctly, and the application continues to call my attemptToRegisterGeofenceAlertForLocation: method attemptToRegisterGeofenceAlertForLocation:
- (void)locationManager:(CLLocationManager *)manager didUpdateLocations:(NSArray *)locations { CLLocation *location = [locations lastObject]; NSDate *eventDate = location.timestamp; NSTimeInterval howRecent = [eventDate timeIntervalSinceNow]; if (abs(howRecent) < 15.0) { [self.locationManager stopUpdatingLocation]; if([self attemptToRegisterGeofenceAlertForLocation:location]) { [[NSNotificationCenter defaultCenter] postNotificationName:kGeofenceSetupSuccess object:nil]; } else { [[NSNotificationCenter defaultCenter] postNotificationName:kGeofenceSetupFailure object:nil]; } } }
So far so good. Here is my user function for registering a relatively small geolocation around the current location of users:
- (BOOL)attemptToRegisterGeofenceAlertForLocation:(CLLocation *)location { // Do not create regions if support is unavailable or disabled if (![CLLocationManager regionMonitoringAvailable]) return NO; // Check the authorization status if (([CLLocationManager authorizationStatus] != kCLAuthorizationStatusAuthorized) && ([CLLocationManager authorizationStatus] != kCLAuthorizationStatusNotDetermined)) return NO; // Clear out any old regions to prevent buildup. if ([self.locationManager.monitoredRegions count] > 0) { for (id obj in self.locationManager.monitoredRegions) { [self.locationManager stopMonitoringForRegion:obj]; } } // If the overlay radius is too large, registration fails automatically, // so clamp the radius to the max value. CLLocationDegrees radius = 100; // meters? if (radius > self.locationManager.maximumRegionMonitoringDistance) { radius = self.locationManager.maximumRegionMonitoringDistance; } // Create the region to be monitored. CLRegion *region = [[CLRegion alloc] initCircularRegionWithCenter:location.coordinate radius:radius identifier:kGeofenceIdentifier]; [self.locationManager startMonitoringForRegion:region]; return YES; }
When a user leaves the geofence area, I answer him like this:
- (void)locationManager:(CLLocationManager *)manager didExitRegion:(CLRegion *)region { if([region.identifier isEqual:kGeofenceIdentifier]) { if([[UIApplication sharedApplication] applicationState] == UIApplicationStateBackground) {
I determined that the application can select the user's location and correctly register geofencing, however, I can not run it on the device itself (iPhone with 3G support). I left the geological region and drove a few miles without receiving any notice. I managed to get an alert in the Simulator, drastically changing my location.
What am I doing wrong?