What would be the best solution in Swift for a precise clock to control external hardware? I need to write a loop function that would fire at a set rate per second (hundreds or thousands Hz) reliably and with high precision.
Asked
Active
Viewed 3,822 times
12
-
Is your question about [ios] or [osx]? – Martin R May 02 '17 at 20:20
-
osx for now but knowing the solution for ios would be helpful as well – Alexander May 02 '17 at 20:31
-
4Apple has a [technical note](https://developer.apple.com/library/content/technotes/tn2169/_index.html#//apple_ref/doc/uid/DTS40013172-CH1-TNTAG10000) on this exact topic. You have to drop pretty low into the Mach kernel functions to get good precision. – Code Different May 03 '17 at 03:16
1 Answers
16
You can define a GCD timer property (because unlike NSTimer
/Timer
, you have to maintain your own strong reference to the GCD timer):
var timer: DispatchSourceTimer!
And then make a timer (probably a .strict
one that is not subject to coalescing, app nap, etc., with awareness of the power/battery/etc. implications that entails) with makeTimerSource(flags:queue:)
:
let queue = DispatchQueue(label: "com.domain.app.timer", qos: .userInteractive)
timer = DispatchSource.makeTimerSource(flags: .strict, queue: queue)
timer.scheduleRepeating(deadline: .now(), interval: 0.0001, leeway: .nanoseconds(0))
timer.setEventHandler {
// do something
}
timer.resume()
Note, you should gracefully handle situations where the timer cannot handle the precision you are looking for. As the documentation says:
Note that some latency is to be expected for all timers, even when a leeway value of zero is specified.

Rob
- 415,655
- 72
- 787
- 1,044
-
1thank you, got it working but sad to see a roughly 0.0005 error for a 5Hz timer. Would dropping down to C help to improve things? – Alexander May 02 '17 at 21:30
-
In [TN2169](https://developer.apple.com/library/archive/technotes/tn2169/_index.html), they consider anything greater that 500 μs an error, so your experience seems to be within their expected margin of error. See https://stackoverflow.com/a/45125092/1271826 for Swift code snippet with high precision timers. – Rob Aug 23 '20 at 22:46
-
FWIW, I tried that sort of high precision timer and got a standard deviation of ~25 μs on iPhone Xs. – Rob Aug 24 '20 at 00:17
-
@Rob I know this is quite old but does a `.strict` flag mean that the timer won't be subject to coalescing, app nap, etc? I could not find any documentation on that claim. – Santiago Alvarez Mar 31 '21 at 01:12
-
Yep. They discussed it in WWDC 2013 video “Improving Power Efficiency with App Nap”. This video (and the code snippets that showed how to use `DISPATCH_TIMER_STRICT`, a.k.a. [`DispatchSource.TimerFlags.strict`](https://developer.apple.com/documentation/dispatch/dispatchsource/timerflags/1780877-strict)) have been taken down, but you can find the [old, third-party transcript online](https://asciiwwdc.com/2013/sessions/209). Or you can just empirically test it. But I'm no longer seeing much documentation at all about App Nap on Apple’s developer site. – Rob Mar 31 '21 at 03:46