Reputation: 2326
We call startTimer function to start a timer. When we wanted to stop it we call stopTimerTest function but after we called stopTimer function the timerTestAction keeps firing. To check the timer condition we used print and print in timerActionTest returns nil.
var timerTest: Timer? = nil
func startTimer () {
timerTest = Timer.scheduledTimer(
timeInterval: TimeInterval(0.3),
target : self,
selector : #selector(ViewController.timerActionTest),
userInfo : nil,
repeats : true)
}
func timerActionTest() {
print(" timer condition \(timerTest)")
}
func stopTimerTest() {
timerTest.invalidate()
timerTest = nil
}
Upvotes: 52
Views: 87229
Reputation: 474
Full working code
import UIKit
class ViewController: UIViewController {
var timer:Timer? = nil
var countValue = 60;
@IBAction func buttonClicked(_ sender: UIButton) {
self.timer?.invalidate()
self.timer = nil
self.timer = Timer.scheduledTimer(timeInterval: 1.0, target: self, selector: #selector(countDown), userInfo: nil, repeats: true)
}
@objc
func countDown() {
if countValue>1 {
countValue -= 1
} else {
self.timer?.invalidate()
self.timer = nil
}
print("\(countValue) Seconds")
}}
Upvotes: 0
Reputation: 2099
Make sure when you call StartTimer
it is nil
and if you call StartTimer
twice without calling StopTimer
. You will lose your original pointer and you can't stop it.
var timer : Timer? = nil {
willSet {
timer?.invalidate()
}
}
Start and Stop timer like ...
func startTimer() {
stopTimer()
guard self.timer == nil else { return }
self.timer = Timer.scheduledTimer(timeInterval: 10, target: self, selector: #selector(self.fetchData), userInfo: nil, repeats: true)
}
func stopTimer() {
guard timer != nil else { return }
timer?.invalidate()
timer = nil
}
Upvotes: 12
Reputation: 6324
Try to make the following changes to your code:
First, you have to change the way you declare timerTest
var timerTest : Timer?
then in startTimer
before instantiating check if timerTest
is nil
func startTimer () {
guard timerTest == nil else { return }
timerTest = Timer.scheduledTimer(
timeInterval: TimeInterval(0.3),
target : self,
selector : #selector(ViewController.timerActionTest),
userInfo : nil,
repeats : true)
}
Finally in your stopTimerTest
you invalidate timerTest
if it isn't nil
func stopTimerTest() {
timerTest?.invalidate()
timerTest = nil
}
Upvotes: 127
Reputation: 299355
Most likely you've called startTimer
twice without calling stopTimerTest
. If you do that, you'll lose your pointer to the original timer and never be able to invalidate it.
The typical approach is to manage invalidation as a part of setting:
var timerTest : Timer? = nil {
willSet {
timerTest?.invalidate()
}
}
Then stopping is just setting to nil:
func stopTimerTest() {
timerTest = nil
}
Upvotes: 45
Reputation: 12303
Check, are you really call stopTimerTest()
, because timerTest.invalidate()
is correct for stopping timer.
func stopTimerTest() {
print("stopTimer")
timerTest.invalidate()
}
Upvotes: 5