Obj-c NSTimer – Slower than expected

| | August 4, 2015

I have to do heavy operation every < 1s. I’m using NSTimer, but its not that accurate as i expected… I’m using 2 timers. One to update data in my model and 2nd to update my views (few labels and custom ‘fancy-circle’ progress bar)

Ok… my code:

_valueTimer = 
  [NSTimer scheduledTimerWithTimeInterval:0.01
                                   target:self
                                 selector:@selector(counterTask)
                                 userInfo:nil
                                  repeats:YES];

_progressTimer =
  [NSTimer scheduledTimerWithTimeInterval:0.1
                                   target:self
                                 selector:@selector(updateViews) // heavy stuff here
                                 userInfo:nil
                                  repeats:YES];

[[NSRunLoop currentRunLoop] addTimer:_progressTimer
                           forMode:NSRunLoopCommonModes]; 

As you can see _progressTimer selector is run every 0.1 sec.
One of the views is my HH:MM:SS time (data from first timer!). It display different time than real time when my progressbar is updating (heavy operation) -> 10 sec in app == 12 sec in real time… Its to much difference. When I comment my progress bar update – it all works correctly

Could you tell me how to force my timer to run exactly after my interval? Or skip one cycle when its too much for it to handle? The most important thing is to not slow down…

Thanks

One Response to “Obj-c NSTimer – Slower than expected”

  1. You can try using a CADisplayLink timer to synchronize animation/drawing with the refresh rate of the device’s display (ie, 60 times per second for iOS devices).

    self.displayLink = [CADisplayLink displayLinkWithTarget:self selector:@selector(handleDisplayLinkTimerFired:)];
    //_displayLink.frameInterval = 3; // slows the updates for debugging
    [_displayLink addToRunLoop:[NSRunLoop mainRunLoop] forMode:NSDefaultRunLoopMode];
    

    Because your method (here, handleDisplayLinkTimerFired:) will be called frequently, you don’t want to do heavy processing or you risk dropping frames.

Leave a Reply