The problem is that the completion block in question was probably not executed in the main thread and therefore did not have a run loop. But timers should be scheduled in the run loop, and although the main thread has one, most background threads don't (unless you add one yourself).
To fix this, in this completion handler, send the timer creation back to the main thread, and it should work fine:
DispatchQueue.main.async { self.timer = Timer.scheduledTimer(timeInterval: 1.0, target: self, selector: #selector(handleTimer(_:)), userInfo: nil, repeats: true) }
Or use a dispatch source timer (a timer that can be scheduled for a background queue and does not require a run loop).
var timer: DispatchSourceTimer! private func startTimer() { let queue = DispatchQueue(label: "com.domain.app.timer") timer = DispatchSource.makeTimerSource(queue: queue) timer.setEventHandler { [weak self] in
The syntax for an earlier version of Swift is in a previous version of this answer .
Rob
source share