I’m trying to learn how to use a timer in Swift, and every solution I look up is broken somehow or beyond my understanding.
I’ve tried with a closure, and without.
With a closure, I can actually get the app to run without crashing, but the timer just repeats 60
, it doesn’t count down and I don’t know why.
let timer = Timer.scheduledTimer(withTimeInterval: 1.0, repeats: true, block: { timer in
var secondsRemaining = 60
print(secondsRemaining)
secondsRemaining -= 1
})
I’ve also tried using an @objc func with selector, but my app crashes right away with error Thread 1: "-[__SwiftValue countdown]: unrecognized selector sent to instance 0x600002970e40"
(I haven’t even gotten to trying the count down yet).
class ViewController: UIViewController {
let timer = Timer.scheduledTimer(timeInterval: 1.0, target: self, selector: #selector(countdown), userInfo: nil, repeats: true)
@objc func countdown() {
print("fire")
}
…
…
}
Any help is appreciated.
EDIT
If I place my variable outside the block, I get an error inside the block Instance member 'secondsRemaining' cannot be used on type 'ViewController'
class ViewController: UIViewController {
var secondsRemaining = 60
let timer = Timer.scheduledTimer(withTimeInterval: 1.0, repeats: true, block: { timer in
print(secondsRemaining)
secondsRemaining -= 1
})
}
But if I create a new project and put the timer inside viewDidLoad()
, it works. I don’t know why.
class ViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
var secondsRemaining = 60
let timer = Timer.scheduledTimer(withTimeInterval: 1.0, repeats: true, block: { timer in
print(secondsRemaining)
secondsRemaining -= 1
})
}
}
4
Answers
Every time your timer fires, a new variable with an initial value of 60 is instantiated, thus always printing 60.
You have to declare your counting variable outside:
Or:
You’re declaring counter inside the timer call. That’s why every time the timer executes it resets the counter to 60 seconds. You need to declare your timer outside the it’s call:
As mentioned in the comments above, don’t reset the variable every single time you get in the closure and change you timer to the following. Create a simple obj function to do whatever logic you want. Also name your functionalists meaningfully
}
Here is the fixed code: