2014-03-31 35 views
0

我有以下代码跟踪用户的位置,并检测用户是否在JSON文件中的指定事件之一,通过匹配当前用户位置的长和拉与长当事件开始时间与当前iPhone时间相等时,然后执行以下指令,触发NSTimer持续5分钟,5分钟后调用此方法onTick(),计算开始时间并且当前时间超过5分钟,如果超过5分钟,则将该事件设置为参加。问题是,当我在iPhone上测试它时,它确实有效,但对于时间间隔超过5分钟的所有事件,即使我只想为当前用户在当时的事件工作!任何人都可以plzzz对我解释这是为什么发生,什么可能是解决..我真的糊涂..测试与位置跟踪NSTimer

这里是我的代码:

.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 { 

} 
+0

由于计时器已经安排,你不需要它的广告向runloop! –

+0

你为什么要将[NSDate日期]翻译成NSString并回到NSDate? –

+0

我不认为这条线是有道理的!请确保您确实要检查此事件的开始时间是否与当前时间相同! [resultString isEqualToString:eventStartTime] –

回答

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方法中做所有事情,因为即使应用程序处于后台,也应该调用它!

+0

emm你正确..但它是必要的,如果我想使用NSTimer我必须调用选择器..是否有任何其他方式? – user3066516

+0

我的意思是你不应该使用NSTimer! (或至少不仅) –

+0

看看我的解决方案的其他答案是不依赖于NSTimer –

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]];   
} 
+0

嗨,我已经测试了我的iPhone设备的代码,因为上面的代码给了我一些警告,但是它没有起作用,所以我在特定的时间去了一个特定的位置,以便我可以看到事件被标记为参加,但不幸的是没有真正出现..你有任何线索为什么会发生? PS,Plzz检查我的更新代码上面的问题>> – user3066516