Iphone (iOS)退出区域时通过locationManager:didExitRegion:发送多个通知

Iphone (iOS)退出区域时通过locationManager:didExitRegion:发送多个通知,iphone,ios,cocoa-touch,core-location,Iphone,Ios,Cocoa Touch,Core Location,我正在开发一个基于位置的应用程序,它利用CLLocationManager区域监控 我使用一个CLLocationManager和一个委托(在启动时设置在主应用程序委托中),我注意到在退出受监控区域时,我经常会收到对我的委托(在locationManager:didExitRegion:)的多个调用,通常是两个调用,但有时更多。有没有其他人经历过这种情况,或者有什么想法会出什么问题 我正在应用程序委托中实例化的类中实例化CLLocationManager,如下所示: _locationM

我正在开发一个基于位置的应用程序,它利用CLLocationManager区域监控

我使用一个CLLocationManager和一个委托(在启动时设置在主应用程序委托中),我注意到在退出受监控区域时,我经常会收到对我的委托(在locationManager:didExitRegion:)的多个调用,通常是两个调用,但有时更多。有没有其他人经历过这种情况,或者有什么想法会出什么问题

我正在应用程序委托中实例化的类中实例化CLLocationManager,如下所示:

    _locationManager = [[CLLocationManager alloc] init];
    _locationManager.desiredAccuracy = kCLLocationAccuracyHundredMeters;
    _locationManager.delegate = self;
我正在设置区域监控,如下所示:

    // The region instance has a radius of 300 meters
    [_locationManager startMonitoringForRegion:region desiredAccuracy:1000];
正如我从中了解到的,提供所需的1000精度意味着locationManager:didExitRegion:只应在我们离开该区域1000米时调用


另外一点——据我所知,我只有在车里(因此行驶速度相当快)才会收到多个突发通知。如果我骑自行车或步行,这似乎不会发生。任何关于我做错了什么(或者这是其他人已经遇到的问题)的指点都是值得赞赏的。

我敢打赌这是你的问题,
locationManager:didExitRegion:
会为iPhone上每个应用程序中的每个位置管理器注册的每个区域调用。您需要将作为参数发送的区域标识符字符串与您希望应用程序当前处理的区域的区域标识符字符串进行比较


发送
[\u locationManager startMonitoringForRegion:region Desired准确性:1000]时您正在创建一个区域,如果它还不存在以进行监视。这与向NSNotification Center添加观察员不同。Apple的region对象会盲目地将通知发送给每个CLLocationManager,然后由后者将消息发送给代理。

首先,文档中并没有指出desiredAccuracy单独决定在生成didExitRegion事件之前您需要离开一个区域多远。如果要微调触发事件的频率,还需要使用distanceFilter,它确定在触发事件之前需要移动的水平移动

如果使用distanceFilter不起作用,我建议如下:

  • 如果您正在使用NSNotificationCenter,请确保已通过[[NSNotificationCenter defaultCenter]removeObserver:self]从通知中删除其他类。您可以选择为此调用指定名称和对象

  • 1000公里是一个大半径,很有可能与附近的许多地区相交。我会尝试将此参数设置为较低的数字,以查看这是否不会减少您收到的退出通知的数量。唯一表明这可能不是解决办法的是,你没有说你也收到了迪登特地区的爆炸声

  • 最后,我将检查在didExitRegionEvent中传递的CLRegion的标识符,看看您是否不能自己设置一个NSRegion字典。您必须在didEnterRegion上为字典设置一个区域,然后在didExitRegion上删除它。因此,在didExitRegion上,您所要做的就是通过检查您是否已经拥有该区域来确保您对该区域感兴趣。我猜CLRegion已经配备了isEqual:和hash,以允许它存储在集合中


  • 祝你好运

    我认为您最好使用小于300米半径的理想精度,即
    kCLOCATIONACURACIHUNDREDMETS
    。你试过了吗? 没有关于基本逻辑的文档,但我假设,
    desiredAccuracy
    可以被视为移动被视为“过境”的最小距离 区域监控基于“重要位置事件”,而不是GPS——否则电池不会持续半天

    如果您使用如此高的
    期望精确度
    ,系统可能会获得不止一个重要的位置事件(这些事件似乎每500米生成一次–也取决于您在该区域拥有多少wifi网络)。 在这种情况下,系统可能会将重大变化导致的当前位置与到您所在区域各边的距离进行比较。 如果您距离您所在区域的另一侧仅1000米以外,它可能会再次通知您,并且仅在您所在区域的每一侧距离1000米以外时停止通知

    设置精度参数的原因是为了避免越境,如果您离边界太近,因此在边界外旅行时看不到内部等

    在我的应用程序中,我尝试了许多不同的半径和精度组合,并选择了500米/100米和100米/10米——这些在我在szenario城市的实际工作中非常有效


    (另请参阅优秀文章系列)

    tl;dr:这非常简单——你可以得到苹果公司提供的关于你正在跨越细胞塔边界的信息——这意味着,根本不是很好的数据

    现在是真实的故事:

    通常,只有两种方法可以确定一个人的位置:

    • 这是高度精确的(几十米),但需要大量的电力使用
    • 通过WiFi。这通常是准确的,尽管WiFi基站可以而且确实会发生变化,这使得它变得模糊。这种方法交叉引用该地区的WiFi站点与一些已知的准确位置,因此它知道何时会看到“FoowFirstation”它与一个特定的区域相关,通过精密仪器测量,或者甚至是其他打开GPS的手机(这是有争议的,我们可能永远不知道应用程序
      -(BOOL)checkForMultipleNotifications:(GeoFenceModel*)fence
      {
        GeoFenceModel *tempFence = [fenceAlertsTimeStamps objectForKey:fence.geoFenceId];
        if(tempFence == nil){
          fence.lastAlertDate = [NSNumber numberWithDouble:[[NSDate date] timeIntervalSince1970]];
          [fenceAlertsTimeStamps setObject:fence forKey:fence.geoFenceId];
          NSLog(@"checkForMultipleNotifications : no Notifications found for Region : %@, Adding to Dictionary with timestamp %.1f",fence.geoFenceId,fence.lastAlertDate.doubleValue);
        }
        else if(([[NSDate date] timeIntervalSince1970] - fence.lastAlertDate.doubleValue) <= 60.0){
          NSLog(@"checkForMultipleNotifications : Multiple region break notifications within 60 seconds, skipping this alert");
          return NO;
        }
        return YES;
      }