【问题标题】:Region Monitoring Glitch on iOS 7 - Multiple Notifications at the same timeiOS 7 上的区域监控故障 - 同时有多个通知
【发布时间】:2023-03-03 20:59:01
【问题描述】:

我已经在 iOS 上开发区域监控大约 2 个月了。最近我们发现了一个故障,在一定半径内(约4.7KM或4700米)的所有区域同时触发。该设备的当前位置甚至不靠近任何区域。我不确定是什么触发了该事件。我通过 StackOverFlow、Apple 开发者论坛等进行了搜索,我没有发现任何与我所面临的问题类似的问题。

在我正在开发的应用程序中,我们正在监控城市(吉隆坡)内的 8 个区域。有一次,我的同事发现他的手机同时触发了 4 个区域通知。下面的地图显示了他的位置、所有被监控的区域、触发 4 个区域通知的潜在半径。

  • 绿色标记是设备收到通知时的位置。
  • 蓝色圆圈是设备的潜在半径(约 4700 米),覆盖了向设备发送通知的 4 个区域。
  • 红色圆圈是每个区域的半径。
  • 地图上还有 2 个其他区域从不发送通知(从不在蓝色圆圈下覆盖)

触发通知的屏幕截图

这是我的位置管理器代码:-

CLLocationManager *locationManager = [LocationTracker sharedLocationManager];
locationManager.delegate = self;
locationManager.desiredAccuracy = kCLLocationAccuracyBestForNavigation;
locationManager.distanceFilter = kCLDistanceFilterNone;

这是我的 didEnterRegion 代码:-

-(void)locationManager:(CLLocationManager *)manager 
        didEnterRegion:(CLRegion *)region{

NSString* message = [NSString stringWithFormat:@"Message"];        
UIApplicationState state = [[UIApplication sharedApplication] applicationState];

if (state == UIApplicationStateBackground || state == UIApplicationStateInactive)
{
   UILocalNotification *notification = [[UILocalNotification alloc] init];
   notification.fireDate = [NSDate date];
   NSTimeZone* timezone = [NSTimeZone defaultTimeZone];
   notification.timeZone = timezone;
   notification.alertBody = message;
   notification.alertAction = @"Show";
   notification.soundName = UILocalNotificationDefaultSoundName;
   [[UIApplication sharedApplication] scheduleLocalNotification:notification];
 }

}

注意:此问题并非每次都会发生,它只会偶尔发生一次。 4700米是我分析了4个触发区域的位置后得出的半径。我不确定这是我的代码、iOS 上的故障还是我所在国家/地区的本地电信公司存在问题。在最新版本的应用程序中,我将 distanceFiter 调整为 10,我们现在正在对其进行测试,看看这是否能解决问题。

//locationManager.distanceFilter = kCLDistanceFilterNone;
locationManager.distanceFilter = 10;

didEnterRegion 方法从不返回用户的位置,我无法像上面显示的示例那样过滤掉半径较大的潜在错误位置。我能做些什么来解决这个故障?

任何面临类似问题的开发者,请站出来分享您解决此问题的经验和解决方案(如果有的话)。谢谢。

【问题讨论】:

  • 您确定您的应用程序没有在后台被杀死,然后由 iOS (7) 稍后启动,因此导致对超过 1 个区域进行检查?
  • 我很确定该应用程序没有被杀死。就算杀了,一个设备位置怎么可能同时出现在这么多不同的区域?该设备的当前位置甚至不靠近我上面提到的 4 个区域中的任何一个。距离设备位置最近的区域是 3000 米。
  • 嗨,我也遇到了同样的问题,你能解决这个问题吗?你在哪个版本的设备上遇到了这个问题。请在这里查看我的问题。stackoverflow.com/questions/25841870/…跨度>

标签: ios objective-c ios7 core-location cllocationmanager


【解决方案1】:

我找到了解决这个奇怪错误的方法。我们已经测试了超过 1 周,到目前为止,我们还没有看到同样的错误。这是解决方案:-

-(void)locationManager:(CLLocationManager *)manager didEnterRegion:(CLRegion *)region{

NSLog(@"didEnterRegion");
CLLocation * lastLocation = [manager location];

BOOL doesItContainMyPoint;

if(lastLocation==nil)
    doesItContainMyPoint = NO;
else{
    CLLocationCoordinate2D theLocationCoordinate = lastLocation.coordinate;
    CLCircularRegion * theRegion = (CLCircularRegion*)region;
    doesItContainMyPoint = [theRegion containsCoordinate:theLocationCoordinate];
}

if(doesItContainMyPoint){
    NSString* message = [NSString stringWithFormat:@"You are now in this region:%@",region.identifier];
    UIApplicationState state = [[UIApplication sharedApplication] applicationState];

    if (state == UIApplicationStateBackground || state == UIApplicationStateInactive)
       {
         UILocalNotification *notification = [[UILocalNotification alloc] init];
         notification.fireDate = [NSDate date];
         NSTimeZone* timezone = [NSTimeZone defaultTimeZone];
         notification.timeZone = timezone;
         notification.alertBody = message;
         notification.alertAction = @"Show";
         notification.soundName = UILocalNotificationDefaultSoundName;
         [[UIApplication sharedApplication] scheduleLocalNotification:notification];
        }
  }
}

我使用CLLocation * lastLocation = [manager location]; 从设备获取最新位置,并使用此坐标查看它是否在 containsCoordinate: 方法的触发区域内。如果在里面,那么只会触发本地通知。

关于这个bug的详细解释和修复方法,您可以访问:iOS Region Monitoring and Location Manager

【讨论】:

  • 这个解决方案对我不起作用,你找到其他解决方案了吗?
  • 现在它可以工作了,当我在“didDetermineState”中添加你的代码时。但是还有一个问题,在检测到任何区域后,它没有被再次检测到,它没有调用 Enter/Exit 方法,有什么解决方案吗?
  • 我不太明白您所说的“不再被检测到”是什么意思。供您参考,iOS 中的区域监控通知仅每 5 分钟发生一次。如果有 2 个区域彼此非常接近,iOS 很可能会触发一个通知而忽略另一个。请阅读:stackoverflow.com/questions/24165599/…
  • 不,这不是我的问题,一旦检测到一个区域,将不会为该区域调用“DidExitRegion”,直到用户从当前检测到的区域移动 10Km,并且如果用户从未旅行这么多距离,他永远不会收到该区域的“进入”通知,即使用户多次从该区域经过。
  • 这个解决方案对我不起作用。使用它,在调用didEnterRegion方法时,如果该区域不包含用户的位置,只有在didExitRegion之后才会再次调用该方法。即使用户多次进入该区域,我们也永远不会收到该区域的“进入/接近”通知。
【解决方案2】:

HERE 是针对 iOS 地理围栏故障的完整证明工作解决方案/修复!

它既可以解决在网络切换(如 wifi 到移动数据)上接收错误的多个事件的问题,反之亦然。它还通过此逻辑/修复为您提供准确的结果/通知

基本上,LocationManager 应该被视为单例,distanceFilter 应该是 kCLDistanceFilterNone,desiredAccuracy 应该是 kCLLocationAccuracyBestForNavigation(我们采用这个是为了获得尽可能高的准确度,因为我们需要对实时地理围栏非常准确的位置进行实时背景监控进入通知发送给用户)

- (void)locationManager:(CLLocationManager *)manager didEnterRegion:(CLRegion *)region
{    

CLLocation * lastLocation = [manager location];

BOOL doesItContainMyPoint;


if(lastLocation==nil)
    doesItContainMyPoint = NO;
else{
    CLLocationCoordinate2D theLocationCoordinate = lastLocation.coordinate;
    CLCircularRegion * theRegion = (CLCircularRegion*)region;

//we need to take new instance of given region for which the iOS triggers entry event..Adding 50.0 meters is needed just to make sure that containsCoordinate method of CLCircularRegion works well.Because there is lag/difference measured in our real time field testing that brought us to this conclusion and it works like a charm.If we do not add this 50.0 meters in the fence for which we are getting this event then there is a chance that containsCoordinate might miss the recent point/coordinate to consider in given region...

    CLCircularRegion * theCircularRegion = [[CLCircularRegion alloc]initWithCenter:theRegion.center radius:theRegion.radius+50.0 identifier:theRegion.identifier];
    doesItContainMyPoint = [theCircularRegion containsCoordinate:theLocationCoordinate];
}

if(doesItContainMyPoint){
    NSLog(@"ItContainMyPoint");
//trigger local notification...

}else{
    NSLog(@"ItDoesNotContainMyPoint");
    //do not trigger local notification...because it is triggered due to switching network(wifi to mobile data and vice versa) Currently user is not at all in the region for which we are getting event of entry
    return;
}

}

【讨论】:

    【解决方案3】:

    这是一个老问题,但让我分享一下我在 Region Monitoring 中关于不准确的 didExit-dEnterRegion 调用的经验:

    需要注意的一点是,如果您在设备上关闭了 Wifi,iOS 设备上地理围栏的可靠性会大大降低。

    在询问者的情况下,您不应该只检查要调试的最后一个位置的.coordinate,还要检查CLLocation 的.horizontalAccuracy。如果关闭 wifi 和 GPS,这可能会显示非常低的准确度(可能的区域很大)。如果您还运行 GPS 位置跟踪,则接受的答案实际上是一个很好的答案。如果不是, .horizo​​ntalAccuracy 可能是一个非常大的数字。区域监控似乎(根据我的经验)不会收听 GPS 更新,因此您无法通过这种方式提高其可靠性。但是启用 WiFi 可以。在市区。

    如果没有 Wifi 和 GPS 技巧(如接受的答案使用),设备所拥有的只是手机信号塔位置。我发现 didExitRegion 和 didEnterRegion 可能不可靠,如果所有设备都必须获取它的位置,是手机信号塔。这是因为基站定位的准确度当然远低于wifi。在这种情况下,低准确度(可能的区域很大)可能意味着它位于提问者的四个区域中的任何一个。甚至可能对单个区域多次调用它,因为它可能突然(基于手机信号塔)认为它在一公里之外,然后意识到它不是,这可能导致 didEnterRegion 被多次调用。

    didExitRegion 也是如此。如果准确率真的很低,系统无法确定您离开该区域直到几公里外(这是评论者的问题之一)

    因此,如果您不确定您的用户是否在使用始终打开 wifi 的应用(您无法在 iOS 上检查或保证),请确保您不要将区域设置得太小或使用已接受的答案GPS ([locationManager startUpdatingLocation]) 以确保您确实在该地区。在这种情况下,还要检查位置是否准确且足够年轻。比如:

    CLLocation * lastLocation = [manager location];
    NSTimeInterval locationAge = -[lastLocation.timestamp timeIntervalSinceNow];
    
    if (lastLocation != nil && locationAge < MAX_AGE && self.currentLocation.horizontalAccuracy <= MAX_ACCURACY) {
        CLLocationCoordinate2D theLocationCoordinate = lastLocation.coordinate;
        CLCircularRegion * theRegion = (CLCircularRegion*)region;
        doesItContainMyPoint = [theRegion containsCoordinate:theLocationCoordinate];
    }
    

    但是,如果有任何方法可以说服用户在使用应用程序时始终启用 Wifi,那就去做吧!它使它更加可靠。

    【讨论】:

      猜你喜欢
      • 2013-11-20
      • 2014-05-23
      • 2011-07-17
      • 1970-01-01
      • 2014-09-13
      • 2015-06-21
      • 1970-01-01
      • 2012-03-07
      • 1970-01-01
      相关资源
      最近更新 更多