Question

An app I'm working on currently sets up region monitoring with the user's current location when the app is backgrounded. When the app becomes active again I am trying to stop monitoring for the region, but it seems to work intermittently with the majority of the time resulting in it failing to act as expected. When the app is backgrounded, I start monitoring for the region and it works fine when I log the details:

- (void)locationManager:(CLLocationManager *)manager didStartMonitoringForRegion:(CLRegion *)region {
    DDLogInfo(@"CREATED REGION: %@", region.identifier);
}

Which results in the following log:

  • "CREATED REGION: regionFor: [real lat here, real lon here] with radius: 100"

When the app wakes up, I call the following function:

- (void)stopMonitoringAllRegions {
    DDLogInfo(@"About to stop monitoring for %d regions", [locationManager monitoredRegions].count);

    // stop monitoring for any and all current regions
    for (CLRegion *region in [[locationManager monitoredRegions] allObjects]) {
        [locationManager stopMonitoringForRegion:region];
    }

    DDLogInfo(@"After stopping, we're currently monitoring for %d regions", [locationManager monitoredRegions].count);
} 

Which results in the following log about 75% of the time:

  • "About to stop monitoring for 1 regions"
  • "After stopping, we're currently monitoring for 1 regions"

and infrequently I get what seems like a success:

  • "About to stop monitoring for 1 regions"
  • "After stopping, we're currently monitoring for 0 regions"

I've tried a couple of things with no success. The regions I'm creating are CLCircularRegions, which inherit from CLRegion so that should work regardless, but in the for-loop I've changed CLRegion to CLCircularRegion with no effect. I was originally using [locationManager monitoredRegions] by itself, which returns an NSSet, so I thought using the allObjects function to get the array would fix the issue, but it hasn't.

I also thought it might be an issue with mutating the array while enumerating, but the only other post I saw on SO said that the above worked for them...

Am I missing something?

Was it helpful?

Solution

If you read up on monitoredRegions, it represents all monitored regions of all CLLocationManager instances, and so is probably controlled by a private dispatch queue - which would explain the delays.

My suggestion would be to keep your own mutable array (or set) around, using it to keep track of what regions are monitored and which are not, and not rely on the location manager for that collection.

Now that its clear you cannot rely on immediate changes to it, I'd design around it rather than try to find some heuristic that seems (today) to work but bites you later.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top