I'm looking to create a countdown timer for SMPTE Timecode (HH:MM:SS:FF) on iOS. Basically, it's just a countdown timer with a resolution of 33.33333ms. I'm not so sure NSTimer is accurate enough to be counted on to fire events to create this timer. I would like to fire an event or call a piece of code every time this timer increments/decrements.
I'm new to Objective-C so I'm looking for wisdom from the community. Someone has suggested the CADisplayLink class, looking for some expert advice.
If you are targeting iOS 4+, you can use Grand Central Dispatch:
This will call that code after 33.333333ms. If is this going to be a loop sorta deal, you may want to use the
dispatch_after_f
function instead that uses a function pointer instead of a block:And then just call
ScheduleWork();
when you want to start the timer. For a repeating loop, I personally think this is a little cleaner than the block method above, but for a one time task I definitely prefer the block method.See the Grand Central Dispatch docs for more info.
Try CADisplayLink. It fires at the refresh rate (60 fps).
This will fire every 2 frames, which is 30 times per seconds, which seems to be what you are after.
Note, that this is tied to video frame processing, so you need to do your work in the callback very quickly.
You basically have no guarantees with either
NSTimer
ordispatch_after
; they schedule code to triggered on the main thread, but if something else takes a long time to execute and blocks the main thread, your timer won't fire.That said, you can easily avoid blocking the main thread (use only asynchronous I/O) and things should be pretty good.
You don't say exactly what you need to do in the timer code, but if all you need to do is display a countdown, you should be fine as long as you compute the SMPTE time based on the system time, and not the number of seconds you think should have elapsed based on your timer interval. If you do that, you will almost certainly drift and get out of sync with the actual time. Instead, note your start time and then do all the math based on that:
Now you will display the correct time code no matter how often the timer is fired. (If the timer doesn't fire often enough, the timer won't update, but when it updates it will be accurate. It will never get out of sync.)
If you use CADisplayLink, your method will be called as fast as the display updates. In other words, as fast as it would be useful, but no faster. If you're displaying the time, that's probably the way to go.