Используйте DispatchSourceTimer
для этой цели, потому что, если у вас есть куча вызовов asyncAfter в будущем). При его объединении общая скорость должна оставаться в значительной степени постоянной, но она будет объединять их вместе, давая вам больше заиканий в ваших таймерах
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()