use*_*343 6 objective-c nstimer
我正在尝试使用NSTimer创建一个Stop-watch样式计时器,每0.1秒递增一次,但有时它似乎运行得太快了.
这就是我做到的方式:
Timer =[NSTimer scheduledTimerWithTimeInterval: 0.1 target:self selector:@selector(updateTimeLabel) userInfo:nil repeats: YES];
Run Code Online (Sandbox Code Playgroud)
然后:
-(void)updateTimeLabel
{
maxTime=maxTime+0.1;
timerLabel.text =[NSString stringWithFormat:@"%.1f Seconds",maxTime];
}
Run Code Online (Sandbox Code Playgroud)
这将在Label中显示计时器的值,稍后我可以将maxTime用作Timer停止的时间...
问题是它运行非常不准确.
有没有一种方法可以确保NSTimer严格每0.1秒严格发射一次?我知道NSTimer不准确,我要求进行调整以使其准确.
谢谢
根据NSTimer文档,它并不准确.
由于典型的运行循环管理各种输入源,因此定时器的时间间隔的有效分辨率被限制在50-100毫秒的量级.如果在长时间标注期间或在运行循环处于不监视定时器的模式下发生定时器的触发时间,则定时器在下次运行循环检查定时器之前不会触发.因此,计时器可能发射的实际时间可能是在计划的发射时间之后的重要时间段.
您可能希望使用dispatch_afterGCD中的功能,这是官方文档为此目的建议的(创建计时器).
如果要在指定的时间间隔后执行一次块,则可以使用
dispatch_after或dispatch_after_f功能.
顺便说一句,我同意Caleb的回答.如果你不像现在这样积累错误,你可能会解决你的问题.如果您使用该-timeIntervalSince:方法存储开始日期并在每次迭代时重新计算时间,那么无论计时器精度如何,您都将获得准确的UI更新.
maxTime=maxTime+0.1;
Run Code Online (Sandbox Code Playgroud)
这是错误的做法。您不想使用计时器来累积经过的时间,因为您会随之累积错误。使用计时器定期触发一个方法,该方法使用 计算经过的时间NSDate,然后更新显示。因此,更改您的代码来执行某些操作:
maxTime = [[NSDate date] timeIntervalSince:startDate];
Run Code Online (Sandbox Code Playgroud)
这是一个你可以用来做你想要的课程:
@interface StopWatch()
@property ( nonatomic, strong ) NSTimer * displayTimer ;
@property ( nonatomic ) CFAbsoluteTime startTime ;
@end
@implementation StopWatch
-(void)dealloc
{
[ self.displayTimer invalidate ] ;
}
-(void)startTimer
{
self.startTime = CFAbsoluteTimeGetCurrent() ;
self.displayTimer = [ NSTimer scheduledTimerWithTimeInterval:0.05 target:self selector:@selector( timerFired: ) userInfo:nil repeats:YES ] ;
}
-(void)stopTimer
{
[ self.displayTimer invalidate ] ;
self.displayTimer = nil ;
CFAbsoluteTime elapsedTime = CFAbsoluteTimeGetCurrent() - self.startTime ;
[ self updateDisplay:elapsedTime ] ;
}
-(void)timerFired:(NSTimer*)timer
{
CFAbsoluteTime elapsedTime = CFAbsoluteTimeGetCurrent() - self.startTime ;
[ self updateDisplay:elapsedTime ] ;
}
-(void)updateDisplay:(CFAbsoluteTime)elapsedTime
{
// update your label here
}
@end
Run Code Online (Sandbox Code Playgroud)
关键点是: