使用位置跟踪测试NSTimer

时间:2014-03-31 21:25:12

标签: ios iphone nstimer cllocationmanager

我有以下代码跟踪用户位置并通过将当前用户位置的长度和纬度与今天事件的长度和纬度匹配来检测用户是否在JSON文件中的一个指定事件中事件开始时间等于当前的iPhone时间然后执行以下指令激活NSTimer 5分钟,并在5分钟后调用此方法onTick(),它将计算起始时间和当前时间之间的差异5分钟后通过,如果仍然超过5分钟,则将此事件设置为有人参加。事情是,当我在我的iPhone上测试它确实有效,但对于所有时间间隔超过5分钟的事件,即使我只想在当时用户当前的活动中工作!任何人都可以向我解释为什么会发生这种情况以及可能是什么解决方案......我真的很困惑......

这是我的代码:

    .h file
    @property (nonatomic, strong) Event *currentEvent;
    @property (nonatomic, strong) CLLocation *currentEventLocation;
    @property (nonatomic, strong) NSDate *arrivalDate;
    @property (nonatomic, strong) CLLocation *currentLocation;
    @property (nonatomic, strong) CLLocation *theNewLocation;



  .m file
- (void) locationManager:(CLLocationManager *)manager didUpdateLocations:(NSArray *)locations {

self.currentLocation = [locations lastObject];

if (self.currentEvent) {
    if ([self.arrivalDate timeIntervalSinceNow]<60*3) {
        if ([self.currentEventLocation distanceFromLocation:self.theNewLocation]<100) {
            [self.currentEvent setHasATTENDED:[NSNumber numberWithBool:TRUE]];
        }
    }
}

self.currentLocation = self.theNewLocation;

for (Event *event in [self loadTodaysEvents]) {

    NSDateFormatter *dateFormatter = [[NSDateFormatter alloc]init];
    NSDate *currentTime = [NSDate date];
    [dateFormatter setDateFormat:@"HH:mm"];
    NSString *resultString = [dateFormatter stringFromDate:currentTime];

    NSString *eventStartTime = event.startingTime;

    // distance
    CLLocationDegrees lat = [event.lat doubleValue];
    CLLocationDegrees lon = [event.longi doubleValue];
    CLLocation *evLocation = [[CLLocation alloc] initWithLatitude:lat longitude:lon];
    double distance = [evLocation distanceFromLocation:self.theNewLocation];

    // CLOSE !
    if (distance <= 100 && [resultString isEqualToString:eventStartTime]) {
        self.arrivalDate = currentTime;
        self.currentEvent = event;
        self.currentEventLocation = evLocation;
        NSTimer *timer = [NSTimer scheduledTimerWithTimeInterval: 180.0
                                                          target: self
                                                        selector: @selector(onTick:)
                                                        userInfo: nil
                                                         repeats: NO];

        NSRunLoop *runner = [NSRunLoop currentRunLoop];
        [runner addTimer:timer forMode: NSDefaultRunLoopMode];
    }
  }
}



- (void)onTick:(NSTimer *)timer
 {
  [self locationManager:nil didUpdateLocations:@[self.currentLocation]];
 }


- (void)locationManager:(CLLocationManager *)manager didFailWithError:(NSError *)error {

 }

2 个答案:

答案 0 :(得分:0)

问题是你的onTick方法不会测试你是否还在同一个活动中!你只需检查任何事件。

你应该这样做:

存储他目前在NSTimer参加的活动以及活动地点:

NSDictionary* userInfo = 
[NSDictionary dictionaryWithObjectsAndKeys:event,@"event",evLocation,@"location", nil]
NSTimer *timer = [NSTimer scheduledTimerWithTimeInterval: 180.0
                                                          target: self
                                                        selector: @selector(onTick:)
                                                        userInfo:userInfo
                                                         repeats: NO];

将上述代码替换为您调用计时器的代码。

当用户移动时,您还必须存储iPhone的currentPosition,以检查他是否离开了活动!

这也应该在locationManager:didUpdateToLocation:fromLocation电话中完成。

例如,使用@property (nonatomic, strong) CLLocation *currentLocation;

locationManager:didUpdateToLocation:fromLocation刚设置self.currentLocation = newLocation;

的第一行

然后在onTick方法中检查您是否仍在接近:

CLLocation *evLocation = timer.userInfo[@"location"];
Event *event = timer.userInfo[@"event"];

double distance = [evLocation distanceFromLocation:self.currentLocation];

   // CLOSE !
    if (distance <= 100) {
    [event setHasATTENDED:[NSNumber numberWithBool:TRUE]];
                 // save
                  NSError *error = nil;
                  if (![_managedObjectContext save:&error])
                     {
                       NSLog(@"Error in saving");
                     }
  }
}

你不需要再次检查时间,因为你已经知道计时器在5分钟后被激活了!

这种方法还有另一个问题!

用户必须在活动期间保持iPhone应用程序正常运行,以便您的应用程序接收定时器回调!您应该只使用locationManager:didUpdateToLocation:fromLocation方法执行所有操作,因为即使应用程序位于后台也应该调用此方法!

答案 1 :(得分:0)

另一个答案应该适用于应用程序在后台!您必须让位置管理员更新位置,以便您知道用户何时移动并且locationManager:didUpdateToLocation:fromLocation:一直被调用!

@property (nonatomic, strong) Event* currentEvent;
@property (nonatomic, strong) CLLocation* currentEventLocation;
@property (nonatomic, strong) NSDate* arrivalDate;
@property (nonatomic, strong) CLLocation* currentLocation;



- (void) locationManager:(CLLocationManager *)manager
     didUpdateToLocation:(CLLocation *)newLocation
            fromLocation:(CLLocation *)oldLocation {

    if (self.currentEvent) {
        if ([self.arrivalDate timeIntervalSinceNow]<60*5) {
            if ([self.currentEventLocation distanceFromLocation:newLocation]<100) {
                [self.currentEvent setHasATTENDED:[NSNumber numberWithBool:TRUE]];
            }
        }
    }
    self.currentLocation = newLocation;

    for (Event *event in [self loadTodaysEvents]) {

        NSDateFormatter *dateFormatter = [[NSDateFormatter alloc]init];
        NSDate *currentTime = [NSDate date];
        [dateFormatter setDateFormat:@"HH:mm"];
        NSString *resultString = [dateFormatter stringFromDate:currentTime];

        NSString *eventStartTime = event.startingTime;

        // distance
        CLLocationDegrees lat = [event.lat doubleValue];
        CLLocationDegrees lon = [event.longi doubleValue];
        CLLocation *evLocation = [[CLLocation alloc] initWithLatitude:lat longitude:lon];
        double distance = [evLocation distanceFromLocation:newLocation];

        // CLOSE !
        if (distance <= 100 && [resultString isEqualToString:eventStartTime]) {
            self.arrivalDate = currentTime;
            self.currentEvent = event;
            self.currentEventLocation = evLocation;
            NSTimer *timer = [NSTimer scheduledTimerWithTimeInterval: 300.0
                                                              target: self
                                                            selector: @selector(onTick:)
                                                            userInfo: nil
                                                             repeats: NO];

            NSRunLoop *runner = [NSRunLoop currentRunLoop];
            [runner addTimer:timer forMode: NSDefaultRunLoopMode];
        }
    } 
}

- (void)onTick:(NSTimer *)timer
{
    [self locationManager:nil didUpdateToLocation:self.currentLocation fromLocation:self.currentLocation];
}

更新代码:

@property (nonatomic, strong) Event* currentEvent;
@property (nonatomic, strong) CLLocation* currentEventLocation;
@property (nonatomic, strong) NSDate* arrivalDate;
@property (nonatomic, strong) CLLocation* currentLocation;



- (void)locationManager:(CLLocationManager )manager didUpdateLocations:(NSArray *)locations { 
    CLLocation currentLocation = [locations lastObject];

    if (self.currentEvent) {
        if ([self.arrivalDate timeIntervalSinceNow]<60*5) {
            if ([self.currentEventLocation distanceFromLocation:newLocation]<100) {
                [self.currentEvent setHasATTENDED:[NSNumber numberWithBool:TRUE]];
            }
        }
    }
    self.currentLocation = newLocation;

    for (Event *event in [self loadTodaysEvents]) {

        NSDateFormatter *dateFormatter = [[NSDateFormatter alloc]init];
        NSDate *currentTime = [NSDate date];
        [dateFormatter setDateFormat:@"HH:mm"];
        NSString *resultString = [dateFormatter stringFromDate:currentTime];

        NSString *eventStartTime = event.startingTime;

        // distance
        CLLocationDegrees lat = [event.lat doubleValue];
        CLLocationDegrees lon = [event.longi doubleValue];
        CLLocation *evLocation = [[CLLocation alloc] initWithLatitude:lat longitude:lon];
        double distance = [evLocation distanceFromLocation:newLocation];

        // CLOSE !
        if (distance <= 100 && [resultString isEqualToString:eventStartTime]) {
            self.arrivalDate = currentTime;
            self.currentEvent = event;
            self.currentEventLocation = evLocation;
            NSTimer *timer = [NSTimer scheduledTimerWithTimeInterval: 300.0
                                                              target: self
                                                            selector: @selector(onTick:)
                                                            userInfo: nil
                                                             repeats: NO];

            NSRunLoop *runner = [NSRunLoop currentRunLoop];
            [runner addTimer:timer forMode: NSDefaultRunLoopMode];
        }
    } 
}

- (void)onTick:(NSTimer *)timer
{
    [self locationManager:nil didUpdateLocations:@[self.currentLocation]];        
}