I\'ve created a test application with timer before implementing it in my project.
It was the first time I\'m using timer.
But the issue is when I implemented timer using
scheduledTimerWithTimeInterval:invocation:repeats:
and scheduledTimerWithTimeInterval:target:selector:userInfo:repeats:
create timers that get automatically added to an NSRunLoop
, meaning that you don't have to add them yourself. Having them added to an NSRunLoop
is what causes them to fire.
With timerWithTimeInterval:invocation:repeats:
and timerWithTimeInterval:target:selector:userInfo:repeats:
, you have to add the timer to a run loop manually, with code like this:
[[NSRunLoop mainRunLoop] addTimer:repeatingTimer forMode:NSDefaultRunLoopMode];
Other answers on here suggest that you need to call fire
yourself. You don't - it will be called as soon as the timer has been put on a run loop.
Also one may want to make sure to add timer on the main thread.
assert(Thread.isMainThread)
let timer = Timer.scheduledTimer(timeInterval: 3, target: self, selector: #selector(YourSelector), userInfo: nil, repeats: true)
The difference between the two is that the timerWithTimeInterval
method returns a NSTimer
object that has not yet been fired. To fire the timer you have to use [timer fire];
On the other hand the scheduledTimerWithTimeInterval
returns an NSTimer
that has already been fired.
So, in your first implementation you were just missing [timer fire];
As a previous answer noted schedule on the main thread, but rather than using assert, put it on the main thread:
@objc func update() {
...
}
DispatchQueue.main.async {
self.timer = Timer.scheduledTimer(timeInterval: 0.01, target: self, selector: #selector(self.update), userInfo: nil, repeats: true)
}
And if async is not desired, try this:
let schedule = {
self.timer = Timer.scheduledTimer(timeInterval: 0.01, target: self, selector: #selector(self.update), userInfo: nil, repeats: true)
}
if Thread.isMainThread {
schedule()
}
else {
DispatchQueue.main.sync {
schedule()
}
}