目前我的位置代码都是单身人士的一部分。我很好奇这是否是造成我问题的原因。我使用位置单身人士作为地理围栏区域和iBeacons的一部分。我在我测试的位置有多个iBeacons,似乎有时一个信标区域的输入会中断前一个区域的退出。我很好奇,如果发生这种情况,因为这是一个单例,如果我应该将其更改为标准类,应用程序委托初始化以启动监视,应用程序将处理发生的每次回调的回调。我认为,因为它是一个单例,所以发生的第二个回调就是在没有完成的情况下停止第一次回调。
你可以从下面的日志中看到我退出了地下室,它启动了一个定时事件,以确保我真正退出地下室(软件过滤器摆脱iBeacons发生的快速退出/输入)。然后我走进了我的客厅,开了另一个地区活动,但我们从未收到消息didExitRegion:地下室退出。
2014-04-25 15:35:22.757 [2761:707] Just Requested Background Time
2014-04-25 15:35:22.761 [2761:707] Basement
2014-04-25 15:35:22.767 [2761:707] Start Timed Event To See If Its A False Exit
2014-04-25 15:35:22.777 [2761:707] Just Requested Background Time
2014-04-25 15:35:22.778 [2761:707] Basement
2014-04-25 15:35:22.780 [2761:707] Start Timed Event To See If Its A False Exit
2014-04-25 15:35:23.751 [2761:707] Just Requested Background Time
2014-04-25 15:35:23.753 [2761:707] didEnterRegion: Living Room
2014-04-25 15:35:23.772 [2761:707] Just Requested Background Time
2014-04-25 15:35:23.774 [2761:707] didEnterRegion: Living Room
2014-04-25 15:35:24.270 [2761:707] Job ID Value
2014-04-25 15:35:24.272 [2761:707] 3208
对nstimer进行更改后的新日志:
2014-04-25 17:13:06.873 [3243:707] Just Requested Background Time
2014-04-25 17:13:06.875 [3243:707] Kitchen
2014-04-25 17:13:06.877 [3243:707] Start Timed Event To See If Its A False Exit
2014-04-25 17:13:06.884 [3243:707] Just Requested Background Time
2014-04-25 17:13:06.885 [3243:707] Kitchen
2014-04-25 17:13:06.886 [3243:707] Start Timed Event To See If Its A False Exit
2014-04-25 17:13:09.146 [3243:707] didExitRegion Basement
2014-04-25 17:13:09.149 [3243:707] Cancelled Exit Of Region: Basement
2014-04-25 17:13:09.881 [3243:707] Job ID Value
2014-04-25 17:13:09.883 [3243:707] 4040
2014-04-25 17:13:09.884 [3243:707] Connection Successful
2014-04-25 17:13:10.878 [3243:707] Cancelled Exit Of Region: Kitchen
2014-04-25 17:13:10.889 [3243:707] Cancelled Exit Of Region: Kitchen
代码已更新:
- (void)locationManager:(CLLocationManager *)manager didEnterRegion:(CLRegion *)region
{
currentRegion = region;
GeofenceObject *gObject = [[GeofenceObject alloc] init];
gObject = [self getObjectForGeofence:region];
//stop multiple notification deliveries
if (notificationDelivered && ![gObject getIsBeacon])
{
notificationDelivered = NO;
return;
}
BOOL alwaysNotify = [[NSUserDefaults standardUserDefaults] boolForKey:@"alwaysNotifyLocation"];
if (![self checkWifi] && ![self checkWWLAN] && ![gObject getIsBeacon])
{
[self notifyNoNetwork:gObject forState:[NSNumber numberWithInt:1]];
return;
}
if ((alwaysNotify && ![gObject getIsBeacon]))
{
[self notifyAlways:gObject forState:[NSNumber numberWithInt:1]];
return;
}
BOOL isInBackground = NO;
if ([UIApplication sharedApplication].applicationState == UIApplicationStateBackground)
{
isInBackground = YES;
}
NSTimer *timer = (NSTimer *)[self.timers objectForKey:[gObject getGeofenceName]];
if (timer != nil)
{
[timer invalidate];
[self.timers removeObjectForKey:[gObject getGeofenceName]];
}
if (isInBackground && [gObject getIsBeacon])
{
[self beginBackgroundTask];
NSLog(@"%@", [@"didEnterRegion: " stringByAppendingString:[gObject getGeofenceName]]);
[self didEnterRegion:region forObject:gObject];
return;
}
if (isInBackground)
{
[self beginBackgroundTask];
NSLog(@"%@",[@"didEnterRegion " stringByAppendingString:[gObject getGeofenceName]]);
[self didEnterRegion:region forObject:gObject];
return;
}
if ([gObject getIsBeacon])
{
NSLog(@"%@", [@"didEnterRegion: " stringByAppendingString:[gObject getGeofenceName]]);
[self didEnterRegion:region forObject:gObject];
}
NSLog(@"%@",[@"didEnterRegion " stringByAppendingString:[gObject getGeofenceName]]);
[self didEnterRegion:region forObject:gObject];
}
- (void)locationManager:(CLLocationManager *)manager didExitRegion:(CLRegion *)region
{
currentRegion = region;
GeofenceObject *gObject = [[GeofenceObject alloc] init];
gObject = [self getObjectForGeofence:region];
//stop multiple notification deliveries
if (notificationDelivered && ![gObject getIsBeacon])
{
notificationDelivered = NO;
return;
}
BOOL alwaysNotify = [[NSUserDefaults standardUserDefaults] boolForKey:@"alwaysNotifyLocation"];
if (![self checkWifi] && ![self checkWWLAN] && ![gObject getIsBeacon])
{
[self notifyNoNetwork:gObject forState:[NSNumber numberWithInt:0]];
return;
}
if ((alwaysNotify && ![gObject getIsBeacon]))
{
[self notifyAlways:gObject forState:[NSNumber numberWithInt:0]];
return;
}
BOOL isInBackground = NO;
if ([UIApplication sharedApplication].applicationState == UIApplicationStateBackground)
{
isInBackground = YES;
}
if (isInBackground && [gObject getIsBeacon])
{
[self beginBackgroundTask];
[gObject setJustExitedRegion:YES];
[self replaceObjectWithUpdate:gObject];
NSDictionary *info = [NSDictionary dictionaryWithObject:region forKey:@"region"];
NSLog(@"%@", [gObject getGeofenceName]);
NSLog(@"%@", @"Start Timed Event To See If Its A False Exit");
[self.timers setObject:[NSTimer scheduledTimerWithTimeInterval:4.0f target:self selector:@selector(checkBackOnExit:) userInfo:info repeats:NO] forKey:[gObject getGeofenceName]];
return;
}
if (isInBackground)
{
[self beginBackgroundTask];
NSLog(@"%@",[@"didExitRegion " stringByAppendingString:[gObject getGeofenceName]]);
[self didExitRegion:region forObject:gObject];
return;
}
if ([gObject getIsBeacon])
{
[gObject setJustExitedRegion:YES];
[self replaceObjectWithUpdate:gObject];
NSDictionary *info = [NSDictionary dictionaryWithObject:region forKey:@"region"];
NSLog(@"%@", [gObject getGeofenceName]);
NSLog(@"%@", @"Start Timed Event To See If Its A False Exit");
[self.timers setObject:[NSTimer scheduledTimerWithTimeInterval:4.0f target:self selector:@selector(checkBackOnExit:) userInfo:info repeats:NO] forKey:[gObject getGeofenceName]];
return;
}
NSLog(@"%@",[@"didExitRegion " stringByAppendingString:[gObject getGeofenceName]]);
[self didExitRegion:region forObject:gObject];
}
- (void)beginBackgroundTask
{
NSLog(@"%@", @"Just Requested Background Time");
bgTask = [[UIApplication sharedApplication] beginBackgroundTaskWithExpirationHandler:^{
NSLog(@"%@", @"Just Cancelled Background Time");
[[UIApplication sharedApplication] endBackgroundTask:bgTask];
bgTask = UIBackgroundTaskInvalid;
}];
}
- (void)checkBackOnExit:(NSTimer *)timer
{
NSDictionary *info = [timer userInfo];
CLRegion *region = [info objectForKey:@"region"];
GeofenceObject *gObject = [[GeofenceObject alloc] init];
gObject = [self getObjectForGeofence:region];
if ([gObject getJustExitedRegion])
{
[self didExitRegion:region forObject:gObject];
NSLog(@"%@",[@"didExitRegion " stringByAppendingString:[gObject getGeofenceName]]);
[gObject setJustExitedRegion:NO];
[self replaceObjectWithUpdate:gObject];
[timer invalidate];
[self.timers removeObjectForKey:[gObject getGeofenceName]];
info = nil;
}else
{
[timer invalidate];
[self.timers removeObjectForKey:[gObject getGeofenceName]];
NSLog(@"%@", [@"Cancelled Exit Of Region: " stringByAppendingString:[gObject getGeofenceName]]);
info = nil;
return;
}
}
答案 0 :(得分:2)
你的问题就在这一行 -
[NSTimer scheduledTimerWithTimeInterval:4.0f target:self selector:@selector(checkBackOnExit:) userInfo:info repeats:NO];
您不会将NSTimer
从scheduledTimerWithTimeInterval
返回的新NSMutableDictionary
存储在任何位置,因此只要该方法退出,它就会被解除分配。您需要将NSTimer添加到属性中。由于您可能同时运行多个计时器,我建议使用@property (retain,nonatomic) NSMutableDictionary *timers;
。
init
在适当的地方(例如self.timers=[[NSMutableDictionary alloc]init];
)
didExitRegion:
然后在[self.timers addObject:[NSTimer scheduledTimerWithTimeInterval:4.0f target:self selector:@selector(checkBackOnExit:) userInfo:info repeats:NO] forKey:gObject.geoFenceName];
didEnterRegion:
在NSTimer *timer=(NSTimer *)[self.timers objectForKey:gObject.geoFenceName]
if (timer != nil) {
[timer invalidate];
[self.timers removeObjectForKey:gObject.geoFenceName];
}
checkBackOnExit:
还有[timer invalidate];
[self.timers removeObjectForKey:gObject.geoFenceName];
方法
{{1}}