NSTimer奇怪的延迟

时间:2011-02-23 20:32:15

标签: iphone

我在viewDidLoad方法中有以下代码。它所做的只是每秒更新一个标签。但是,当我运行此代码时,它显示虚拟文本,稍等一下,然后显示8秒而不是9,然后是8 ..

所以看起来它正在跳过9,是否有可能解决这个问题?在计算剩余时间时,我是否应该舍入小数?

感谢您的时间!

//Just dummy text
self.lblTime.text = @"Tid: 0h 0min 10sec";

NSDate *expireDate = [[NSDate alloc] initWithTimeInterval:10 sinceDate:[NSDate date]];
self.expires = expireDate;
[expireDate release];


self.timer = [NSTimer scheduledTimerWithTimeInterval:1.0 target:self selector:@selector(updateTimerDisplay) userInfo:nil repeats:YES];
[[NSRunLoop currentRunLoop] addTimer:self.timer forMode:UITrackingRunLoopMode]; 

在updateTimerDisplay中我有:

//Gets the time right now    
NSDate *now = [NSDate date];

//Stores the difference in seconds between when the test was started and now.
NSTimeInterval interval = [self.expires timeIntervalSinceDate:now];

//Gets the number of hours
NSInteger hours = interval / 3600;

interval = (int)interval % 3600;

//Gets the number of seconds
NSInteger minutes = interval / 60;

interval = (int)interval % 60;

NSInteger seconds = interval;

//Updates the label
self.lblTime.text = [NSString stringWithFormat:@"Time: %dh %dmin %dsec", hours, minutes, seconds];

2 个答案:

答案 0 :(得分:2)

NSTimer无法保证在正确的时间间隔内完全启动。你可以确定的唯一一点就是定时器不会过早启动(假设你的设备的时钟以准确的速度运行),但它很可能会发射得太晚。

在你的情况下,即使计时器发出的时间太晚,你也会得到错误的结果,因为你没有四舍五入seconds值,你只是截断它。您应该考虑舍入seconds和/或更频繁地启动计时器(例如每0.2或0.1秒)。

答案 1 :(得分:1)

首先,我建议使用[NSDate dateWithTimeIntervalSinceNow:10]代替[[NSDate alloc] initWithTimeInterval:10 sinceDate:[NSDate date]][self.expires timeIntervalSinceNow]代替[self.expires timeIntervalSinceDate:[NSDate date]]。这些更简洁。

另请注意,由于self.expires在第二组代码中的日期早于now,因此interval否定,因为间隔因为 now实际上是self.expires以来的间隔。您的代码似乎没有考虑到这一事实。

最后,如果你将expires设置为将来10秒,然后让你的计时器在一秒钟内开启,你可能已经错过了9秒的标记。这是因为所有计时器本质上都不是100%准确,因此可能已经过了略多于1秒。假设已经过了1.01秒,那么剩下10 - 1.01 = 8.99秒,使用整数数学将被截断为剩余8秒。这在我看来是导致你的错误。我通常建议每隔一秒(每十分之一秒左右)更频繁地触发你的计时器以避免这些问题。

如果您有兴趣,这是temporal aliasing的一个例子。