Cocoa NSTimer不准确?
我正在使用Cocoa NSTimer不准确?,cocoa,nstimer,Cocoa,Nstimer,我正在使用NSTimer更新一个标签,该标签显示每分钟的当前时间。我在整分钟的日期(例如2:23:00而不是2:22:17)启动计时器。问题是,NSTimer似乎工作不准确,这意味着它有时发射得太早(这导致(例如)下午2:23,而实际上是下午2:24) 是否有任何修复/解决方法 编辑:以下是我如何启动计时器: NSTimer *clockTimer = [[NSTimer alloc] initWithFireDate:[NSDate nextFullMinuteDate]
NSTimer
更新一个标签,该标签显示每分钟的当前时间。我在整分钟的日期(例如2:23:00而不是2:22:17)启动计时器。问题是,NSTimer
似乎工作不准确,这意味着它有时发射得太早(这导致(例如)下午2:23,而实际上是下午2:24)
是否有任何修复/解决方法
编辑:以下是我如何启动计时器:
NSTimer *clockTimer = [[NSTimer alloc] initWithFireDate:[NSDate nextFullMinuteDate]
interval:60.0
target:self
selector:@selector(updateClocks:)
userInfo:nil
repeats:YES];
[[NSRunLoop currentRunLoop] addTimer:clockTimer
forMode:NSDefaultRunLoopMode];
[clockTimer release];
顺便说一句,我试着在火灾日期上加上几毫秒,这似乎有帮助,但似乎找到一个合适的时间间隔来添加是偶然的
编辑2:好的,所以我手动将计时器设置为在一整分钟后0.05秒启动,然后在60.0秒后再次启动。下面是我在被调用方法中记录的内容:
0.048728
0.047153
0.046484
0.044883
0.043103
如您所见,
NSTimer
实际上并没有使用60秒的时间间隔,而是稍微短一点的时间间隔。我假设您从当前时间开始,然后每次NSTimer
发生故障时,您都会在原始时间上增加一分钟,然后显示它。您应该使用计时器:每次计时器关闭时,重新读取当前时间并显示它。您应该将计时器设置为每秒启动,而不是每分钟启动。但不要每秒钟更新标签。只需比较当前时间的新分钟数是否与上次更新标签时的分钟数不同,如果是,则更新标签。好吧,我刚刚编写了自己的小NSTimer
包装,名为MinuteTimer
,以“解决”问题。我已经上传到了。这样做的目的是,每当计时器启动得太快以至于日期有可能被错误显示时,就重置计时器
由于这是管道胶带编程,我仍然渴望听到其他答案 来自:
计时器不是实时机制;只有当其中一个
已添加计时器的运行循环模式正在运行且可启用
检查计时器的启动时间是否已过。因为各种各样的
输入源一个典型的运行循环管理,有效解决
计时器的时间间隔限制在50-100之间
毫秒。如果计时器的触发时间发生在长调用或
当运行循环处于不监视计时器的模式时
直到下次运行循环检查计时器时,计时器才会启动。
因此,计时器可能触发的实际时间可以是
预定点火时间后的一段重要时间
这意味着NSTimer
非常不准确
如果编写“秒表”,可以使用NSTimer
向用户显示结果,同时(我最喜欢的课程之一)跟踪时间。这一点概述如下:
NIRTimer *nirTimer;
NSTimer *timer;
- (void)start {
nirTimer = [[NIRTimer alloc]init];
timer = [NSTimer scheduledTimerWithTimeInterval:0.01 target:self selector:@selector(timerFired:) userInfo:nil repeats:YES];
[nirTimer start];
- (void)timerFired:(NSTimer *)timer {
[self displayTimeToUser:[nirTimer seconds]];
}
在上面的代码中,n计时器
可能不准确,但准确的时间由n计时器
保持,它每隔0.01
秒向用户显示一次
如果您确实需要在准确的时间运行特定的代码,我找到的最佳解决方案是使用NSThread
和usleep()
:
在这种情况下,将timerRunning
设置为NO
以停止计时器。如果您尝试执行的操作不是线程安全的,您可能还希望使用对象为nil waitUntilDone:NO的[self-performselectornmainthread:@selector(doSomething)]
而不是[self-doSomething]
有关线程的精彩世界的更多信息,请查看。您还应该更频繁地启动计时器,而不是每分钟启动一次。因为计时器似乎启动得太早。比如2:23:59.999而不是2:24:00。至少我认为是这样的。对,所以有时候你的时间会减少1分钟,最多1分钟。尝试每秒钟或每10秒(或任何你确定的最小可接受错误)启动一次计时器。如果不知道你是如何计算时间间隔和开始计时的,很难说你是如何计算
nextFullMinuteDate
?@PeterHosey:look@PeterHosey:allow,查看我在下面的答案中编写和发布的MinuteTimer
课程。这应该可以让您快速创建SSCCE。抱歉,这听起来效率很低。
BOOL timerRunning;
- (void)start {
timerRunning = YES;
[NSThread detachNewThreadSelector:@selector(timer) toTarget:self withObject:nil]; //make a new thread
}
- (void)timer {
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc]init]; //Make an autorelease pool since we're in a new thread
NIRTimer *timer = [[NIRTimer alloc]init]; //Make an NIRTimer
while (timerRunning) {
[timer reset];
[timer start];
[self doSomething];
usleep(10000 - [timer microseconds]); //Wait for .01 seconds which is 10000 microseconds (a microsecond is 1/1000000th of a second) - the time it took to accomplish whatever we were doing
}
//Clean up
[timer release];
[pool release];
}