我是否错误地处理位置更新?

时间:2014-04-25 21:01:41

标签: ios objective-c cllocationmanager ibeacon

目前我的位置代码都是单身人士的一部分。我很好奇这是否是造成我问题的原因。我使用位置单身人士作为地理围栏区域和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;
    }
}

1 个答案:

答案 0 :(得分:2)

你的问题就在这一行 -

[NSTimer scheduledTimerWithTimeInterval:4.0f target:self selector:@selector(checkBackOnExit:) userInfo:info repeats:NO];

您不会将NSTimerscheduledTimerWithTimeInterval返回的新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}}