11

I try to get the iPhone4 to monitor regions and notify me by call didEnterRegion or didExitRegion. I can't get it to work. I was reading probably all related enries here, plus a couple more articles on the web....iOS just don't call my CLLocationManagerDelegate methods. What did I do:

I have a simple AppDelegate which implements also the CLLocationManagerDelegate methods for didEnterRegion and didExitRegion. Within these methods I simply use a UILocalNotification to report the event. From a ViewController I create a Region (the current Location) with aRadius of 1000meters.

oliverk
  • 111
  • 1
  • 3

3 Answers3

44

Here are some things to check:

  1. Before you start monitoring regions in your code, call [CLLocationManager regionMonitoringAvailable] and [CLLocationManager regionMonitoringEnabled] to make sure the service is available and enabled on the user's phone.

  2. Make sure you have the location manager's delegate property set to the object where you've implemented locationManager:didEnterRegion: and/or locationManager:didExitRegion:.

  3. Make sure you don't have any typos in those method signatures. A small capitalization error would cause delivery of these messages to fail. Copy/paste these into your code and make sure they match:

    - (void)locationManager:(CLLocationManager *)manager didEnterRegion:(CLRegion *)region
    { /* Handle enter */ }
    
    - (void)locationManager:(CLLocationManager *)manager didExitRegion:(CLRegion *)region
    { /* Handle exit */ }
    
  4. Make sure your delegate also implements locationManager:monitoringDidFailForRegion:withError:, as it may tell you why the service is failing.

    - (void)locationManager:(CLLocationManager *)manager monitoringDidFailForRegion:(CLRegion *)region withError:(NSError *)error
    {
        NSLog(@"Region monitoring failed with error: %@", [error localizedDescription]);
    }
    
  5. One reason a monitoring failure like this may occur is that Core Location imposes a limit on the number of regions an app is allowed to monitor. In practice this limit seems to be about ten regions per app. So make sure you remove regions you don't need using stopMonitoringForRegion:, and monitor only those regions nearest the user as recommended by Apple's Location Awareness Programming Guide:

    You should always be judicious when specifying the set of regions to monitor. Regions are a shared system resource and the total number of regions available systemwide is limited. For this reason, Core Location limits the number of regions that may be simultaneously monitored by a single application. To work around these limits, you should consider registering only those regions in the user’s immediate vicinity. As the user’s location changes, you can remove regions that are now farther way and add regions coming up on the user’s path. If you attempt to register a region and space is unavailable, the location manager calls the locationManager:monitoringDidFailForRegion:withError: method of its delegate with the kCLErrorRegionMonitoringFailure error code.

  6. Hopefully obvious, but make sure you're calling startMonitoringForRegion:desiredAccuracy: after setting your delegate.

  7. When you initialize the CLRegion object that you're monitoring using initCircularRegionWithCenter:radius:identifier:, make sure you use a unique identifier for each region.

  8. If your locationManager:didEnterRegion: and locationManager:didExitRegion: methods are getting called properly when the app is active, but not when the OS relaunches your app in the background after it's been killed, then you may not be properly initializing your location manager and setting its delegate in that case. If you cross a registered region boundary when the app isn't running, the OS will launch your app in the background, which you can detect using if ([launchOptions objectForKey:@"UIApplicationLaunchOptionsLocationKey"]]) {} in the application:didFinishLaunchingWithOptions: method of your app delegate. Your app probably won't load any views when it's launched in the background like this, so you need to make sure application:didFinishLaunchingWithOptions: invokes some code path that instantiates your location manager object and sets its delegate in this case. As soon as your location manager's delegate property gets set, any pending region monitoring events will be delivered.

cduhn
  • 17,818
  • 4
  • 49
  • 65
  • monitoringDidFailForRegion was the culprit for me when trying to add a couple of hundred regions. Great answer, thanks! – James Zaghini Aug 22 '12 at 10:28
  • in my case,The monitor region radius must >= 450,else the didEnter/didLeave method will not be called – Jagie Oct 19 '12 at 02:12
  • What the region radius must >=450? I want radius to be 5m for each regain. My didEnterRegion and didExitRegion are firing but at inconsistent times; maybe this could be why? It is inconsistent that the radius is like 150m instead of 5m, which is what I set it as. help! – coolcool1994 Mar 16 '14 at 07:46
  • Is it true that monitor region radius must be greater than 450m? I m trying to work with 5m, and the actual registered radius for didEnterRegion and didExitRegion is more like 150m when I actually tested it outside with my iPhone. Is this the limit of the map kit? – coolcool1994 Mar 16 '14 at 07:51
  • Thanks a lot!!! I make a project with iBeacons and I had this problem. I spend two days trying to understand why didEnterRegion is not calling, your answer solved my problem (article 8)! – tagirkaZ Aug 05 '14 at 11:11
  • 1
    Number 6 is now deprecated. –  Jul 23 '16 at 09:00
  • In the `locationManagerDidPauseLocationUpdates` callback (which takes 15 minutes to happen) I create a region. Going into my devices's settings >> privacy >> location services >> MyApp I do see that the filled purple arrow turns into non-filled arrow with a purple stroke indicating that my app is no longer tracking constantly, rather it's tracking using geofence. I've set it with a radius of `50` and set the `region.notifyOnExit = true`. – mfaani Jul 21 '17 at 12:07
  • I did all this and to test it, I placed a breakpoint which triggers the startMonitoring region, once I hits there I started moving. The problem is I don't see consistent behaviors! I tried this like 5 times already. Only once the app was launched through the geofence...The other 4 times, no matter how much I drove away...app wasn't launched—to startTrackingLocationAgain! Any thoughts? – mfaani Jul 21 '17 at 12:10
  • Yeah, I got similar results when I ran similar tests around 6 years ago (!). I don't know if Apple's implementation has changed since then, but the experiments I ran at the time suggested that when the app was closed iOS wouldn't use GPS to check the geofence unless some other app happened to request standard location services. It behaved as though it was using whatever location estimate it could collect passively, which in some cases seemed to be a very rough approximation based on the nearest cell towers. This is a reasonable choice to conserve power, but wasn't at all clear from the docs. – cduhn Jul 22 '17 at 01:14
2

There is a known bug with iOS 5.1 Simulator where the region monitoring delegate methods are not called. My experience with it is it will call the first method triggered (either in or out) but won't call any more after that. I have filed radars with Apple to this fact, but have been mostly ignored for the current iteration. They did respond asking if it was working in the iOS 6 beta, which it is. I don't expect them to fix it for 5.1 at all.

You can download the 5.0 simulator which still works, or download the iOS 6 beta (if you are a paid dev) and test your location stuff there. Outside that, we would need to see some code showing if everything is set up correctly. I'm guessing if the region monitoring icon shows up, you are doing it right and are just victim of the simulator bug.

Bill Burgess
  • 14,054
  • 6
  • 49
  • 86
2

Same here. I am trying too to get didEnterRegion and notify me. What I see is that the method never gets called. So I am having a custom check in (newLocation, oldLocation function)

allocate a distance and :

{
distance = [newLocation distanceFromLocation:(your location)];
if(distance < 300){
[appDelegate Notify:@"Entering "];
}

significantlocationchanges sucks!!

Rahul Patel
  • 5,858
  • 6
  • 46
  • 72
harishkashyap
  • 114
  • 1
  • 8