iOS 7上的区域监控故障-同时发出多个通知
我已经在iOS上开发了大约2个月的区域监控。最近,我们发现了一个小故障,某个半径(约4.7公里或4700米)内的所有区域同时触发。设备的当前位置甚至不靠近任何区域。我不确定是什么触发了这一事件。我在StackOverFlow、Apple开发者论坛等网站上进行了搜索,没有发现任何与我面临的问题类似的问题 在我正在开发的应用程序中,我们正在监测城市内的8个地区(吉隆坡)。有一次,我的同事发现他的手机同时触发了4个区域的通知。下面的地图显示了他的位置、所有监控区域以及触发4个区域通知的潜在半径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个区域通知的潜在半径 绿
- 绿色标记是接收通知时设备的位置李>
- 蓝色圆圈是设备的潜在半径(约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
(我们采用这种方法是为了获得尽可能高的准确度,因为我们需要对位置进行实时后台监控,非常准确,以便向用户发送实时地理围栏进入通知)
你确定你的应用程序没有被激活吗