my code:
let operationStart = Date()
for i in 0...20 {
DispatchQueue.main.asyncAfter(deadline: .now() + 0.5 * Double(i)) {
let distance = operationStart.distance(to: Date())
print("operation \(i) executed after \(distance)")
}
}
Output:
operation 0 executed after 0.001116037368774414 operation 1 executed after 0.5226989984512329 operation 2 executed after 1.0015490055084229 ... operation 9 executed after 4.940060019493103 operation 10 executed after 5.499879002571106 operation 11 executed after 6.049391031265259 operation 12 executed after 6.0494760274887085 operation 13 executed after 7.105716943740845 operation 14 executed after 7.105777978897095 operation 15 executed after 8.189378023147583 operation 16 executed after 8.189532995223999 operation 17 executed after 9.30673599243164 operation 18 executed after 9.306856036186218 operation 19 executed after 10.423419952392578 operation 20 executed after 10.423549056053162
how to avoid this? I need to execute operations with equal delays.
Use DispatchSourceTimer
for this purpose because if you have a bunch of asyncAfter calls in the future). When its coalescing, the overall speed should remain largely consistent, but it will coalesce them together, giving you more stuttering in your timers
let operationStart = Date()
let queue = DispatchQueue(label: "com.domain.app.timer")
var timer = DispatchSource.makeTimerSource(queue: queue)
var i = 0
//for i in 0...20 {
timer.schedule(deadline: .now(), repeating: 0.5, leeway: .seconds(0))
timer.setEventHandler { // `[weak self]` only needed if you reference `self` in this closure and you want to prevent strong reference cycle
let distance = operationStart.distance(to: Date())
i = i+1
if i == 20 {
timer.cancel()
}
print("operation \(i) executed after \(distance)")
}
timer.resume()