1

I am doing an app which needs a timer. I have tried NSTimer but NSTimer always loses or gets delayed. Is there a class in the iOS SDK which can log time accurately. An accuracy between 20ms and 40ms is okay. I'd like to be able to change an image in a fixed time interval.

NSTimer *timer1 = [NSTimer scheduledTimerWithTimeInterval:.04f target:self    selector:@selector(timer1) userInfo:nil repeats:YES];
- (void)timer1
{
   NSLog(@"timer1 timer %@",[NSDate date]);
}
Pavan
  • 17,840
  • 8
  • 59
  • 100
joebo
  • 235
  • 1
  • 3
  • 6
  • 10
    Is your period and your shift key broken? – dasdom Mar 16 '12 at 13:13
  • 1
    The issue is not the accuracy of the timer, but rather the queuing delay from the time the timer triggers to the time the service routine is invoked. If you're utilizing a scheme that runs in the UI thread then there is no way to get around that. – Hot Licks Jul 28 '13 at 12:12

4 Answers4

6

Use CADisplayLink for this. It fires at the system frame rate: 60 fps, or 17 ms.

If you want a longer interval you can set it to fire at a multiple of the frame rate, e.g. every 2nd or 3rd frame.

CADisplayLink *displayLink = [CADisplayLink displayLinkWithTarget:self selector:@selector(timer1)];
displayLink.frameInterval = 2;
[displayLink addToRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode];

It's meant to be used for UI that should update every n frames.

Don't use dispatch_after. As the name would suggest, the only guarantee is that your block will execute after a particular time. If anything blocks the thread, your block will have to wait.

bcattle
  • 12,115
  • 6
  • 62
  • 82
  • This is incredibly useful, I had no idea it existed before now. I bent myself into pretzels for years in the Windows environment trying to get animation properly synced with the refresh rate, and here's this simple iOS component *driven* by the refresh rate. – MusiGenesis Apr 29 '15 at 21:15
4

NSTimer is not a high-resolution timer. From the NSTimer class documentation:

Because of the various input sources a typical run loop manages, the effective resolution of the time interval for a timer is limited to on the order of 50-100 milliseconds.

In addition to link suggested by @CJ Foley, you can check out dispatch_after function.

FluffulousChimp
  • 9,157
  • 3
  • 35
  • 42
  • i also have seen this in the nstimer class documentation ,so i want to find some efficient class to get a accurate time interval to do some periodic action – joebo Mar 17 '12 at 04:32
  • As bcattle's answer states, dispatch_after doesn't guarantee execution at a certain time, only _after_ a certain time. `CADisplayLink` is a better bet. – Bernem May 04 '16 at 15:44
3

Have you considered using the dispatch source timer? From what I observed thus far, this timer is very precise.

Here is a link to one of apple's programming guide:

http://developer.apple.com/library/ios/#documentation/General/Conceptual/ConcurrencyProgrammingGuide/GCDWorkQueues/GCDWorkQueues.html#//apple_ref/doc/uid/TP40008091-CH103-SW1

Just check the sub section: "Creating a timer".

ebp
  • 61
  • 4
0

Perhaps your results are a false negative due to how you're testing NSDate?

This question discusses how to get millisecond accuracy from NSDate.

Community
  • 1
  • 1
CJ Foley
  • 101
  • 4
  • 1
    NSDate is really a good class to get a accurate time ,but in my question i want to get a accurate time interval to do some periodic action ,just like nstimer – joebo Mar 17 '12 at 04:26