I know this is a super basic question, I am trying to refactor my code atm and am running into trouble with the timer. All I am trying to do is just get a simple countdown timer to print to the console
Here is my code snippet right now
VC------
var seconds = 60
override func viewDidLoad() {
super.viewDidLoad()
self.modelInstance.gameTimerMethod(timeParam: self.seconds)
}
MODEL-----
func gameTimerMethod(timeParam : Int) {
gameTimer = Timer.scheduledTimer(timeInterval: 1.0, target: self, selector: #selector(decreaseGameTimer(secondsParam:)), userInfo: timeParam, repeats: true)
print (timeParam)
}
func decreaseGameTimer(secondsParam: Int) {
var printNumber = secondsParam
printNumber -= 1
print (printNumber)
}
Ideally what I want this to do in the console is simply countdown from 60 for now at a rate of one number per second. Although the console is logging at a rate of one number per second, it is for some reason repeatedly logging the number 105553117734207, instead of a 60 seconds countdown.
Thanks!
The value passed to decreaseGameTimer
is the Timer
instance. It has a property userInfo
that has a reference to the object passed to the Timer
constructor.
Create a class
to hold your count, and then pass an instance of that class to the timer's userInfo
:
class Model {
class TimerInfo {
var count: Int
// Pointer to function or closure to call when value changes
var callback: ((Int) -> Void)?
init(start: Int, callback: @escaping (Int) -> Void) {
count = start
self.callback = callback
}
deinit {
print("TimerInfo deinit")
}
}
@objc func decreaseGameTimer(_ timer: Timer) {
if let userInfo = timer.userInfo as? TimerInfo {
userInfo.count -= 1
// call callback with new value
userInfo.callback?(userInfo.count)
print(userInfo.count)
if userInfo.count == 0 {
print("done")
timer.invalidate()
}
}
}
func gameTimerMethod(timeParam: Int, callback: @escaping (Int) -> Void) {
_ = Timer.scheduledTimer(timeInterval: 1, target: self,
selector: #selector(decreaseGameTimer),
userInfo: TimerInfo(start: timeParam, callback: callback),
repeats: true)
}
}
Then you'd call it like this:
override func viewDidLoad() {
super.viewDidLoad()
// The closure that follows the gameTimerMethod call is using trailing
// closure syntax. It gets passed to gameTimerMethod as the second
// parameter named callback. This closure will get called every
// second until the timer finishes.
self.modelInstance.gameTimerMethod(timeParam: self.seconds) { value in
self.label.text = "\(value)"
}
// Just for fun, lets run a second one at the same time
self.modelInstance.gameTimerMethod(timeParam: 10) { value in
self.label2.text = "\(value)"
}
}