【问题标题】:Timer won't stop after 45 minutes计时器在 45 分钟后不会停止
【发布时间】:2013-10-22 06:29:32
【问题描述】:

我有这个 NSTimer,我希望它在 45 分钟后停止,但它不会停止。 我做错了什么?

TIMER_COUNT = 45

HOURS_IN_HOURS = 60

HOURS_IN_DAY = 24

- (void)start
{
    self.timerCountdown = [NSTimer scheduledTimerWithTimeInterval:1.0 target:self selector:@selector(updateCountdown) userInfo:nil repeats: YES];
}

- (void)stop
{
    [self.timerCountdown invalidate];
    self.timerCountdown = nil;
}

- (void)updateCountdown
{
    NSDate *currentDate = [NSDate date];
    NSDate *finalTime = [currentDate dateByAddingTimeInterval:(TIMER_COUNT * HOURS_IN_HOUR)];

    NSCalendar *calendar = [NSCalendar currentCalendar];

    NSDateComponents *componentsHours   = [calendar components:NSHourCalendarUnit fromDate:currentDate];
    NSDateComponents *componentMinuts   = [calendar components:NSMinuteCalendarUnit fromDate:currentDate];
    NSDateComponents *componentSeconds  = [calendar components:NSSecondCalendarUnit fromDate:currentDate];

    NSCalendar *gregorianCalendar = [[NSCalendar alloc] initWithCalendarIdentifier:NSGregorianCalendar];
    NSDateComponents *componentsDaysDiff = [gregorianCalendar components:NSDayCalendarUnit
                                                                fromDate:currentDate
                                                                  toDate:finalTime
                                                                 options:0];

    NSLog(@"%20d Days, %02d Hours, %02d Minutes, %02d Seconds.", componentsDaysDiff.day, HOURS_IN_DAY - componentsHours.hour, HOURS_IN_HOUR - componentMinuts.minute, HOURS_IN_HOUR - componentSeconds.second);

    if ([currentDate compare:finalTime] == NSOrderedSame)
    {
        NSLog(@"Done.");
        [self stop];
    }
}

提前致谢。

【问题讨论】:

  • 小时数,真的吗?
  • 这是一个错误 MINUTES_IN_HOURS

标签: ios objective-c nsdate nstimer nsdatecomponents


【解决方案1】:

因为您的currentDate 将在您的计时器每次滴答时保持设置。每次updateCountdown 方法运行时,[NSDate date] 都会将currentDate 设置为当前时间。因此finalTime 总是比currentDate 早45 分钟。您应该创建一个startDate 属性并将其设置在start 方法中:

- (void)start
{
    self.timerCountdown = [NSTimer scheduledTimerWithTimeInterval:1.0 target:self selector:@selector(updateCountdown) userInfo:nil repeats: YES];
    self.startDate = [NSDate date];
}

然后检查updateCountdown方法中的属性:

if ([self.startDate compare:finalTime] == NSOrderedSame)
{
    NSLog(@"Done.");
    [self stop];
}

或者,您可以使用一个整数来表示您期望的滴答数,然后在每次计时器滴答时从整数中减一。 像这样的:

- (void)start
{
    self.timerCountdown = [NSTimer scheduledTimerWithTimeInterval:1.0 target:self selector:@selector(updateCountdown) userInfo:nil repeats:YES];
    self.countdown = TIMER_COUNT * HOURS_IN_HOUR;
}

- (void)updateCountdown
{
    self.countdown--;

    //your code

    if (self.countdown == 0)
    {
         NSLog(@"Done.");
         [self stop];
    }
}

【讨论】:

  • 您是否考虑过使用一个整数来表示您期望的滴答数(秒),然后每次从整数中减去一个滴答声?当整数为零时,您将完成:) 它比 NSDate 方法更具可读性。我已经编辑了我的答案并添加了一个示例。
【解决方案2】:
- (void)start {
   NSString *startTime = [NSDate date];

   NSDateComponents *durationComponents = [[[NSDateComponents alloc] init] autorelease];
   durationComponents.minutes = 45;

   NSCalendar *gregorianCalendar = [NSCalendar currentCalendar];

   self.endTime = [calendar dateByAddingComponents:durationComponents
                                            toDate:startTime
                                           options:0];

   self.timerCountdown = [NSTimer scheduledTimerWithTimeInterval:1.0 
                                                          target:self           
                                                        selector:@selector(updateCountdown)
                                                        userInfo:nil 
                                                         repeats:YES];
}

- (void)stop {
    [self.timerCountdown invalidate];
    self.timerCountdown = nil;
}

- (void)updateCountdown {
    NSDate *currentTime = [NSDate date];

    NSCalendar *calendar = [NSCalendar currentCalendar];

    NSDateComponents *currentTimeComponents = [calendar components:(NSHourCalendarUnit | NSMinuteCalendarUnit |NSSecondCalendarUnit)
                                                          fromDate:currentTime];


    if ([currentTime compare:self.endTime] == NSOrderedDescending) {
        [self stop];
    }
}

【讨论】:

    【解决方案3】:

    您不需要 startDate 属性。
    而且您不应该检查日期是否相等。这不太可能发生。 使用该比较:

    if ([finalTime compare:[NSDate date]] == NSOrderedAscending)
    {
         NSLog(@"Done.");
         [self.timerCountdown invalidate];
         [self stop];
    }
    

    这意味着 finalTime 在时间上早于当前时间。

    【讨论】:

      猜你喜欢
      • 2014-08-07
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-09-05
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多