Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Swift - Timer doesn't stop

Tags:

ios

swift

timer

I have the following code:

class firstVC: UIViewController {
    var timer : Timer?

    func scheduledTimerWithTimeInterval(){
        timer = Timer.scheduledTimer(timeInterval: 60, target: self, 
        selector: #selector(self.anotherFunc), userInfo: nil, repeats: 
        true)
    }

    override func viewDidAppear(_ animated: Bool) {
        scheduledTimerWithTimeInterval()
    }
}

I'm trying to stop the timer without success:

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

override func viewDidDisappear(_ animated: Bool) {
    super.viewDidDisappear(animated)
    stopTimer()
}

override func viewWillDisappear(_ animated: Bool) {
    super.viewWillDisappear(animated)
    stopTimer()
}

I even tried to put the stop function in applicationWillResignActive And in applicationDidEnterBackground but it didn't stop:

firstVC().stopTimer()

Your help will be appreciated, thank you.

like image 269
Shlomi Avatar asked Oct 06 '17 17:10

Shlomi


1 Answers

As others have said, you are creating multiple timers without killing the old one before starting a new one. You need to make sure you stop any current timer before starting a new one.

What I do is to make my timers weak. I then use the code `myTimer?.invalidate() before trying to create a new timer:

class firstVC: UIViewController {
    weak var timer : Timer?

    func scheduledTimerWithTimeInterval(){
        timer?.invalidate()
        timer = Timer.scheduledTimer(timeInterval: 60, target: self, 
        selector: #selector(self.anotherFunc), userInfo: nil, repeats: 
        true)
    }
}

By making your timer weak, the only thing that keeps a strong reference to the timer is the run loop. Then, when you invalidate it, it immediately gets released and set to nil. By using optional chaining to call the invalidate method, it doesn't do anything if it's already nil, and stops it and causes it to go nil if it IS running.

Note that this approach only works if you create your timer in one shot using one of the scheduledTimer() factory methods. If you try to create a timer first and then add it to the run loop, you have to use a strong local variable to create it or it gets released as soon as you create it.

like image 140
Duncan C Avatar answered Nov 15 '22 03:11

Duncan C