Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Region monitoring current location doesn't notify on exit

I'm trying to test region monitoring, for that I'm getting current location like this:

- (void)startLocationTracking
{
    CLLocationManager *locationManager = [[CLLocationManager alloc] init];

    // Start location manager
    if ([CLLocationManager locationServicesEnabled] && [CLLocationManager authorizationStatus] == kCLAuthorizationStatusAuthorized) {
        locationManager = [LocationTracker sharedLocationManager];
        locationManager.delegate = self;
        [locationManager startMonitoringSignificantLocationChanges];
    }
}

And tracking first location with region monitoring like this:

-(void)locationManager:(CLLocationManager *)manager didUpdateLocations:(NSArray *)locations
{
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        CLRegion *region = [[CLRegion alloc] initCircularRegionWithCenter:manager.location.coordinate radius:300 identifier:@"first location initializer"];

        NSLog(@"0: %@", manager.location);
        NSLog(@"1: %@", region);

        [manager startMonitoringForRegion:region];
        NSLog(@"[locationManager startMonitoringForRegion:%@];", region);
    });
}

Then in every exit from current region I'm monitoring the new location like this:

- (void)locationManager:(CLLocationManager *)manager didEnterRegion:(CLRegion *)region
{
    NSLog(@"%s, %@", __PRETTY_FUNCTION__, region);
}

- (void)locationManager:(CLLocationManager *)manager didExitRegion:(CLRegion *)region
{
    NSLog(@"%s, %@", __PRETTY_FUNCTION__, region);

    NSArray *allRegions = manager.monitoredRegions.allObjects;

    if (allRegions.count > 0) {
        for (CLRegion *reg in allRegions) {
            [manager stopMonitoringForRegion:reg];
        }
    }

    CLLocationCoordinate2D cord = CLLocationCoordinate2DMake(manager.location.coordinate.latitude, manager.location.coordinate.longitude);
    CLRegion *regionNew = [[CLRegion alloc] initCircularRegionWithCenter:cord radius:300 identifier:@"new region"];

    NSLog(@"region: %@", region);
    NSLog(@"regionNew: %@", regionNew);

    [manager startMonitoringForRegion:regionNew];
}

I'll explain what I expect to happen:

  1. Register current location in region monitoring.
  2. Notify user exit current region.
  3. On exit log and register again the current location as region.

This doesn't happen.

Where I'm wrong?

I tried on simulator with 'Freeway Drive'.

UPDATE:

Tested and work, due to Apple bug in geofencing, app will support only 7.1+, pretty bad but I don't have an another idea.

like image 371
Idan Moshe Avatar asked Jun 11 '14 14:06

Idan Moshe


People also ask

Does it notify the person when you check their location on iPhone?

They don't get any notification or there isn't any log of lookup incidents made available to them. The location is sent from the friends device only when you request to see it.

How do you set location alerts on iPhone?

Get notified when your friend arrives at or leaves a location. Tap People at the bottom of the screen, then tap the name of the person you want to be notified about. Below Notifications, tap Add, then tap Notify Me. Choose whether you want to be notified when a friend arrives at or leaves a location.

What is geofencing in IOS?

Overview. Region monitoring (also known as geofencing) is a way for your app to be alerted when the user enters or exits a geographical region. You might use region monitoring to perform location-related tasks.

Does find my phone send notification?

It's sole job is to track people and would be the best approach to this. Expanding on my last comment to link to the question, "Find My Friends" does not notify the person when you are tracking them if you are on each others friend lists.


1 Answers

I think the way you implement the region monitoring might cause some problems.

Here are the reasons:-

  1. Inside the startLocationTracking method, your locationManager is a local object that does not extend over the life cycle of that method. It also means that every time you call startLocationTracking, there will be a new locationManagerobject that is allocated with a new block of memory.

    To solve this problem: You should use a singleton locationManager that is a shared locationManager for the entire life cycle of the Application.

  2. I believe you should not startMonitoringForRegion inside the delegate method -(void)locationManager:(CLLocationManager *)manager didUpdateLocations:. The reason is, if you call startLocationTracking more once, there will be more than one locationManager. Multiple locationManagers could monitor the same region which may cause multiple notifications.

  3. After you call [manager startMonitoringForRegion:region];, the region will not be monitored immediately. If you do not believe believe me, try the follow code:-

    [locationManager startMonitoringForRegion:region];
    NSLog(@"%@",locationManager.monitoredRegions);
    

You will find out that the region that you just monitored will not be inside the locationManager.monitoredRegions. Since this is handled on the iOS level, so, I think it might need a few minutes for the region to be ready to be monitored.

You should also understand other limitations for Region Monitoring in iOS:-

https://developer.apple.com/library/mac/documentation/CoreLocation/Reference/CLLocationManager_Class/CLLocationManager/CLLocationManager.html

An app can register up to 20 regions at a time. In order to report region changes in a timely manner, the region monitoring service requires network connectivity.

In iOS 6, regions with a radius between 1 and 400 meters work better on iPhone 4S or later devices. (In iOS 5, regions with a radius between 1 and 150 meters work better on iPhone 4S and later devices.) On these devices, an app can expect to receive the appropriate region entered or region exited notification within 3 to 5 minutes on average, if not sooner.

Note: Apps can expect a notification as soon as the device moves 500 meters or more from its previous notification. It should not expect notifications more frequently than once every five minutes. If the device is able to retrieve data from the network, the location manager is much more likely to deliver notifications in a timely manner.

I don't know what your app is about, I believe you should redesign the flow of your app. You should try to monitor the region outside of the delegate methods.

For more information about the Singleton LocationManager, you may check out this answer: Background Location Services not working in iOS 7. There is a complete project on GitHub that contains a Singleton LocationManager class that I named as LocationTracker.

You might also want to check out a glitch for Region Monitoring in iOS 7 that I found out a month ago (with a workaround to solve the glitch): Region Monitoring Glitch on iOS 7 - Multiple Notifications at the same time

like image 100
Ricky Avatar answered Sep 30 '22 18:09

Ricky