iOS 7上的区域监控故障-同时发出多个通知

iOS 7上的区域监控故障-同时发出多个通知,ios,objective-c,ios7,core-location,cllocationmanager,Ios,Objective C,Ios7,Core Location,Cllocationmanager,我已经在iOS上开发了大约2个月的区域监控。最近,我们发现了一个小故障,某个半径(约4.7公里或4700米)内的所有区域同时触发。设备的当前位置甚至不靠近任何区域。我不确定是什么触发了这一事件。我在StackOverFlow、Apple开发者论坛等网站上进行了搜索,没有发现任何与我面临的问题类似的问题 在我正在开发的应用程序中,我们正在监测城市内的8个地区(吉隆坡)。有一次,我的同事发现他的手机同时触发了4个区域的通知。下面的地图显示了他的位置、所有监控区域以及触发4个区域通知的潜在半径 绿

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

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

  • 绿色标记是接收通知时设备的位置
  • 蓝色圆圈是设备的潜在半径(约4700米),覆盖向设备发送通知的4个区域
  • 红色圆圈是每个区域的半径
  • 地图上还有另外两个地区从不发送通知(蓝色圆圈下从不覆盖)
已触发通知的屏幕截图

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

CLLocationManager *locationManager = [LocationTracker sharedLocationManager];
locationManager.delegate = self;
locationManager.desiredAccuracy = kCLLocationAccuracyBestForNavigation;
locationManager.distanceFilter = kCLDistanceFilterNone;
-(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];
 }

}
这是我的didEnterRegion代码:-

CLLocationManager *locationManager = [LocationTracker sharedLocationManager];
locationManager.delegate = self;
locationManager.desiredAccuracy = kCLLocationAccuracyBestForNavigation;
locationManager.distanceFilter = kCLDistanceFilterNone;
-(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;
方法dienterregion永远不会返回用户的位置,我无法像上面的示例那样过滤出具有大半径的潜在坏位置。我能做些什么来解决这个问题


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

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

-(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:方法触发的区域内。如果它在内部,则只会触发本地通知


有关此错误的详细说明和修复方法,您可以访问:

这是一个老问题,但让我分享我在区域监控方面关于不准确的didExit-didEnterRegion调用的经验:

需要注意的一点是,如果在设备上关闭Wifi,iOS设备上geofence的可靠性会大大降低

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

如果没有Wifi和GPS技巧(如accepted answer使用的),该设备所拥有的只是手机发射塔的位置。我发现,如果所有的设备都是手机发射塔,那么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];
}
CLLocation*lastLocation=[manager location];
NSTimeInterval locationAge=-[lastLocation.timestamp TimeIntervalenceNow];
如果(lastLocation!=nil&&locationAge是iOS地理围栏故障的全面验证工作解决方案/修复方案!

它既可以解决在网络交换机(如wifi到移动数据)上接收错误的多个事件的问题,也可以解决在网络交换机(如wifi到移动数据)上接收错误的多个事件的问题。此外,它还可以使用此逻辑/修复程序为您提供准确的结果/通知

基本上,
LocationManager
应被视为单例,而distanceFilter应为
KCLDistanceFilterOne
,所需的精确度应为
kCLLocationAccuracyBestForNavigation
(我们采用这种方法是为了获得尽可能高的准确度,因为我们需要对位置进行实时后台监控,非常准确,以便向用户发送实时地理围栏进入通知)


你确定你的应用程序没有被激活吗