locationManager:didStartMonitoringForRegion:错误区域的回调

时间:2013-12-13 20:08:25

标签: ios objective-c cllocationmanager

我正在使用locationManager:didStartMonitoringForRegion:进行区域监控。有时回调包含错误的区域,即使CLLocationManager.monitoredRegions中显示的右侧区域。

也是如此

locationManager:didStartMonitoringForRegion:消息:

- (void)locationManager:(CLLocationManager *)manager didStartMonitoringForRegion:(CLRegion *)region {
    NSLog(@"Started monitoring %@ region", region.identifier);
    NSLog(@"Monitored regions: %@", self.locationManager.monitoredRegions);
}

这里是一个示例输出(经常/经过改变以保存地点)

2013-12-13 20:01:34.047 N[] Started monitoring Hamburg region
2013-12-13 20:01:34.048 N[] Monitored regions: {(
    CLCircularRegion (identifier:'Hamburg', center:<+47.0,+8.1>, radius:1000.00m),
    CLCircularRegion (identifier:'Zürich', center:<+47.0,+8.0>, radius:500.00m),
    CLCircularRegion (identifier:'St.Gallen', center:<+47.0,+9.0>, radius:5000.00m)
)}
2013-12-13 20:01:42.070 N[] Started monitoring Hamburg region
2013-12-13 20:01:42.072 N[] Monitored regions: {(
    CLCircularRegion (identifier:'Hamburg', center:<+47.0,+8.1>, radius:1000.00m),
    CLCircularRegion (identifier:'Zürich', center:<+47.0,+8.0>, radius:500.00m),
    CLCircularRegion (identifier:'St.Gallen', center:<+47.0,+9.0>, radius:5000.00m)
)}
2013-12-13 20:01:46.837 N[] Started monitoring Hamburg region
2013-12-13 20:01:46.839 N[] Monitored regions: {(
    CLCircularRegion (identifier:'Hamburg', center:<+47.0,+8.1>, radius:1000.00m),
    CLCircularRegion (identifier:'Zürich', center:<+47.0,+8.0>, radius:500.00m),
    CLCircularRegion (identifier:'St.Gallen', center:<+47.0,+9.0>, radius:5000.00m)
)}

我开始在didUpdateLocations进行监控,在我致电startMonitoringSignificantLocationChanges

后回电话
- (void)locationManager:(CLLocationManager *)manager didUpdateLocations:(NSArray *)locations{
    NSLog(@"%s", __PRETTY_FUNCTION__);
    [manager stopMonitoringSignificantLocationChanges];
    if (locations && [locations count]){
        CLLocation* position = [locations lastObject];
        NSLog(@"New Location latitude: %f longitude %f", position.coordinate.latitude, position.coordinate.longitude);
        //self.geofences.allValues is containing Hamburg,Zürich and St.Gallen
        for(CLCircularRegion *geofence in self.geofences.allValues) {
            if(![self.locationManager.monitoredRegions containsObject:geofence]){
                [self.locationManager startMonitoringForRegion:geofence];
            }
            if([geofence containsCoordinate:[position coordinate]]){
                [self locationManager:manager didEnterRegion:geofence];
            }
        }
    }
}

didEnterRegion@synchronized以保证原子性。

有什么想法吗?

1 个答案:

答案 0 :(得分:0)

我无法理解为什么它会反复注册同一个区域。我的怀疑会导致我在那里放一些额外的NSLog调用以验证你的源代码,self.geofences的内容。我要做的另一件事是在那里放置一个中断来观察For循环中的值和条件。

我要检查的其他两件事:

  1. 确认您从if(![self.locationManager.monitoredRegions containsObject:geofence]){获得了预期结果。 CLLocationManager中的对象不保证与您最初注册的对象相同。您应该使用isEqualToString测试正确的标识符。您可能会在书写时无意中替换您的地区。
  2. 如果该地区已经注册,我认为您不需要致电didEnterRegion。在发布之间报告边界事件。即使应用程序被终止,它也应该在重新启动时自动处理。
  3. 如果没有一个可以解释这个问题,我会看看你是如何以及何时开始/停止位置服务的。是否有可能每个调用都是didUpdateLocations方法的另一个迭代?

    我希望第一次调用它时,在一个全新的会话中,monitoredRegions为空,因此您的过程按预期工作。我看到了后续位置更新可能出现的不可预测行为的原因。

    我首先要完全改变你的for循环。

    if (locations && locations.count) {
        CLLocation* position = [locations lastObject];
        NSSet *regionIdentifiers = [self.locationManager.monitoredRegions valueForKey:@"identifier"];
        NSSet *regionsForMonitoring = [NSSet setWithArray:self.geofences.allValues];
        NSSet *unMonitoredRegions = [regionsForMonitoring objectsPassingTest:^BOOL(id obj, BOOL *stop) {
            CLCircularRegion *regionForTest = (CLCircularRegion *)obj;
            if (![regionIdentifiers containsObject:regionForTest.identifier]) {
                return YES;
            } else {
                return NO;
            }
        }];
    
        for (CLCircularRegion *geofence in unMonitoredRegions) {
            [self.locationManager startMonitoringForRegion:geofence];
            // We'll check if we are in the new region as it was not previously monitored
            if([geofence containsCoordinate:[position coordinate]]){
                [self locationManager:manager didEnterRegion:geofence];
            }
        }
    }