Swift Invalidate Timer Doesn't Work

swift invalidate timer doesn't work

The usual way to start and stop a timer safely is

var timer : Timer?

func startTimer()
{
if timer == nil {
timer = Timer.scheduledTimer(timeInterval: timeInterval, target: self, selector: #selector(timerFired), userInfo: nil, repeats: true)
}
}

func stopTimer()
{
timer?.invalidate()
timer = nil
}

startTimer() starts the timer only if it's nil and stopTimer() stops it only if it's not nil.

You have only to take care of stopping the timer before creating/starting a new one.

Timer does not invalidate

You might be starting multiple timers. If you hit the line of code that creates a timer before the current one has been invalidated, then you will have two active timers, only one of which you can invalidate.

To prevent this possibility, call invalidate on scoreTimer before creating a new timer:

scoreTimer.invalidate()
scoreTimer = Timer.scheduledTimer(timeInterval: 0.05, target: self, selector: #selector(updatePassengerScore), userInfo: nil, repeats: true)

The other way to handle it is to change scoreTimer to an optional, and then only create a timer if scoreTimer is nil.

var scoreTimer: Timer?

...

if scoreTimer == nil {
scoreTimer = Timer.scheduledTimer(...
}

...

scoreTimer?.invalidate()
scoreTimer = nil

Swift timer won't work after invalidating and reinitiating

The reason was that the timer starts executing in other thread, not in main thread.

Timer will not Invalidate swift 4

Your problem lies in this part of your code.

Timer.scheduledTimer(timeInterval: 1, target: self, selector: (#selector(timeoutPeriod)), userInfo: nil, repeats: true)

You're creating a Timer but not setting it into the Timer variable you created var timer = Timer()

To fix this you just have to set your Timer variable correctly.

self.timer = Timer.scheduledTimer(timeInterval: 1, target: self, selector: (#selector(timeoutPeriod)), userInfo: nil, repeats: true)

Timer keeps working after invalidate() and nil

You are almost certainly assigning precentageTimer twice without invalidating it in between. This is a very common mistake. The function that includes self.precentageTimer = is probably being called multiple times before viewWillDisappear is called. Since you tied it to a button press, it's likely happening if the button is pressed twice.

The usual solution is to add a willSet to percentageTimer like this (and you do not want percentageTimer to be !; it absolutely should be ? because it can be legitimately nil):

var precentageTimer: Timer? {
willSet {
percentageTimer?.invalidate()
}
}

Timer doesn't stop on swift

you are creating another instance of timer inside FireTimer() function with same name, just remove and try

Swift - Timer doesn't stop

After research I found a solution,

The only thing that worked for me is to create functions in AppDelegate file and call them when needed,

Here is the code, the timerSwitch function:

    func timerSwitch()
{
if (timerStatus) {
checkStateTimer = Timer.scheduledTimer(
timeInterval: 60,
target:self,
selector: #selector(self.yourFunction),
userInfo: nil, repeats: true)
} else {
checkStateTimer?.invalidate()
}
}

func stopTimer()
{
timerStatus = false
timerSwitch()

}

func startTimer()
{
timerStatus = true
timerSwitch()

}

While 'yourFunction' is what you want to execute when the timer starts,

In my case is sending heartbeat.


Then I called the timerSwitch is the following functions in AppDelegate:

    func applicationWillResignActive(_ application: UIApplication) {
stopTimer()
}

func applicationDidEnterBackground(_ application: UIApplication) {
stopTimer()
}

func applicationDidBecomeActive(_ application: UIApplication) {
startTimer()
}

Swift | The timer wont stop on invalidate call, rather speeds up?

As far as I can recognize, you have 2 mistakes.

First one is mentioned by the other answer. It is a true suggestion that you shouldn't always add a new UIButton and should use just hide/unhide property for each button.

Second mistake is on how you add a target. You are using .allTouchEvents, however you might intent to use .touchUpInside as your control state.

Kindly see the below corrected code for your reference:

import UIKit

class ViewController: UIViewController {

@IBOutlet weak var titleLabel: UILabel!

var startButton: UIButton!
var stopButton: UIButton!
var timer: Timer!
var counter: Double = 0.0

override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.

startButton = UIButton(frame: CGRect(x: 0, y: UIScreen.main.bounds.height * 0.9 , width: UIScreen.main.bounds.width, height: UIScreen.main.bounds.height * 0.1))
startButton.setTitle("Start Timer", for: .normal)
startButton.setTitleColor(.white , for: .normal)
startButton.backgroundColor = .red
startButton.addTarget(self, action: #selector(playButton(_:)), for: .touchUpInside)
self.view.addSubview(startButton)
self.startButton.isHidden = false

stopButton = UIButton(frame: CGRect(x: 0, y: UIScreen.main.bounds.height * 0.9 , width: UIScreen.main.bounds.width, height: UIScreen.main.bounds.height * 0.1))
stopButton.setTitle("Stop Timer", for: .normal)
stopButton.setTitleColor(.white , for: .normal)
stopButton.backgroundColor = .red
stopButton.addTarget(self, action: #selector(pauseButton(_:)), for: .touchUpInside)
self.view.addSubview(stopButton)
self.stopButton.isHidden = true
}

@objc func playButton(_ sender : Any) {
timer = Timer.scheduledTimer(timeInterval: 1, target: self , selector: #selector(updateTimer), userInfo: nil, repeats: true)

startButton.isEnabled = false
stopButton.isEnabled = true
startButton.isHidden = true
stopButton.isHidden = false
}

@objc func pauseButton(_ sender: Any) {
timer.invalidate()

stopButton.isHidden = true
startButton.isHidden = false
startButton.isEnabled = true
stopButton.isEnabled = false
}

@objc func updateTimer(_ sender : Any)
{
counter += 0.1
titleLabel.text = String(format: "%.1f", counter)
}
}


Related Topics



Leave a reply



Submit