NSTimer accuracy

I am trying to use NSTimer to create a Stop-Watch style timer that increments every 0.1 seconds, but sometimes it works too fast.

Here is how I did it:

Timer =[NSTimer scheduledTimerWithTimeInterval: 0.1 target:self selector:@selector(updateTimeLabel) userInfo:nil repeats: YES]; 

and then:

 -(void)updateTimeLabel { maxTime=maxTime+0.1; timerLabel.text =[NSString stringWithFormat:@"%.1f Seconds",maxTime]; } 

This will display the timer value in the shortcut, and later I can use maxTime as the timer stop time ...

The problem is that it works very inaccurately.

Is there a way in which I can make sure that NSTimer fires strictly every 0.1 seconds for sure? I know that NSTimer is not accurate, and I ask you to configure it to be accurate.

thanks

+6
source share
4 answers

Here is a class that you can use to do what you want:

 @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 

Key points are:

  • Make your time by saving the system time when the stopwatch runs into a variable.
  • when the stopwatch is stopped, calculate the elapsed time by subtracting the start time of the stopwatch from the current time
  • refresh your display with a timer. It doesn't matter if your timer was accurate or not. If you are trying to guarantee that updates are displayed for at least 0.1 s, you can try setting the timer interval to 1/2 of the minimum update time (0.05 s).
+5
source

According to the NSTimer documentation NSTimer it does not have to be accurate.

Due to various input sources, a typical trigger cycle is controlled, the effective resolution of the time interval for the timer is limited to about 50-100 milliseconds. If timers are triggered during a long callout or when the cycle cycle is in a mode that the timer does not control, the timer does not work until the next timer test cycle. Therefore, the actual time during which the timer is triggered potentially can be a significant period of time after the planned firing time.

You can use the dispatch_after function from the GCD, which is suggested by the official documentation for this purpose (creating a timer).

If you want to execute a block once after a certain time interval, you can use the dispatch_after or dispatch_after_f function.


By the way, I agree with Caleb's answer. You will probably solve your problems if you do not accumulate errors, as now. If you save the start date and recalculate the time at each iteration using the -timeIntervalSince: method, you will get an accurate update of the user interface, regardless of the accuracy of the timer.

+8
source
 maxTime=maxTime+0.1; 

This is the wrong way. You do not want to use the timer to accumulate elapsed time, because an error will accumulate with it. Use a timer to periodically run a method that calculates elapsed time using NSDate and then updates the display. So, change your code to do something:

 maxTime = [[NSDate date] timeIntervalSince:startDate]; 
+4
source

NSTimer does not guarantee accuracy, although in practice it is usually (if you are not doing anything in your main topic ...). However, this is perfectly reasonable for updating the display ... just do not use the callback to calculate your timer. Save the current time when you start your timer, and get the difference between now and when you started every time the timer fires. Then it really doesn’t matter how accurately NSTimer works, it only affects how many times per second your screen is refreshed.

+2
source

Source: https://habr.com/ru/post/948500/


All Articles