CLLocationManager didExitRegion never called

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) { // Fire a UILocationNotification } else { // Fire a UIAlertView } } } 

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?

+4
source share
3 answers

It turns out the solution to this problem was to ensure that the CLLocationManager was initialized in the main thread. According to Apple documentation:

The configuration of your location manager object should always be performed on a thread with an active startup cycle, for example, your main thread application.

+1
source

It looks like your radius is 100M (good). The distance filter is also set to 100M as well, which can simply fight you. In the simulator you get very accurate updates because you need to skip them. In the real world, you get less accurate coordinates from Wi-Fi approximation and cell triangulation.

My experience is that if I use kCLLocationAccuracyBest to filter the distance, I get very good results. Since the monitoring of the region is already running from the system, you are not going to remove the battery, just installing the filter in the best way.

+1
source

You already have your answer, but sometimes the problem may be because you don’t go out too much and sit for too long, or sometimes you do it, but since you are in the region, it’s very small, like 5 meters (which something you should never do), and you moved 100 meters

When testing the monitoring code of your region in iOS Simulator or on devices, be aware that events in the region may not occur immediately after the border of the region intersects. To prevent false notifications, iOS does not deliver region notifications until a certain threshold conditions are met . In particular, the location of users must cross the border of the area, move away from the border at a minimum distance , and remain at that minimum distance for at least 20 seconds until the notification is reported.

Certain threshold distances are determined by hardware and are now available. For example, if Wi-Fi is disabled, monitoring the region is much less accurate. However, for testing purposes, you can assume that the minimum distance is about 200 meters .

From Apple Documentation: Monitoring Regions

0
source

All Articles