Swift 3 Timer not firing

21,408

Good Practice: In startTimer() check that the timer has not already been created and make the assignment. In stopTimer() check that the timer exists before calling invalidate, and set the timer back to nil.

Also, for your selector make sure you have the @objc prefix. You should be able to get a working timer with the code provided. Happy coding!

class SomeClass {
    var timer: Timer?

    func startTimer() {
        guard timer == nil else { return }
        timer = Timer.scheduledTimer(timeInterval: 0.1, target: self, selector: #selector(test), userInfo: nil, repeats: true)
    }

    func stopTimer() {
        guard timer != nil else { return }
        timer?.invalidate()
        timer = nil
    }

    @objc func test() {

    }
}
Share:
21,408
Admin
Author by

Admin

Updated on July 09, 2022

Comments

  • Admin
    Admin almost 2 years

    I've been trying to utilize Timer in Swift and I've simplified it town to the following:

    func startTimer () {
        timer = Timer.scheduledTimer(timeInterval: 0.1, target: self, selector: #selector(ViewController.test), userInfo: nil, repeats: true)
    }
    func test () {
        print("FIRED")
    }
    

    I would like to call this from another function and have verified the startTimer function works, but the timer doesn't fire. Does this have something to do with the RunLoop? I'm fairly new to coding so any explanation would be appreciated.

  • Alex Blair
    Alex Blair over 7 years
    One last thing, I don't think ViewController.test is required in your selector parameter, test should work just fine.
  • R.P. Carson
    R.P. Carson almost 7 years
    why does checking to see if its nil matter before you set it to nil
  • Alex Blair
    Alex Blair over 6 years
    It prevents calling invalidate() on a potentially nil object. For instance, lets say you call stopTimer() in multiple functions. It fires once, invalidates the timer, and is set back to nil. If stopTimer() is called again in succession, without reinitializing the timer, you would receive a fatal error. This is because the timer has already been deallocated. Both guard statements are in place to keep starting and stopping the timer in sync.
  • R.P. Carson
    R.P. Carson over 6 years
    but it uses optional chaining and if timer is nil, invalidate wont be called
  • Alex Blair
    Alex Blair over 6 years
    That's true! @R.P.Carson.
  • Tom Spee
    Tom Spee over 6 years
    What if startTimer() has a completion block depending on the test() code?
  • Alex Blair
    Alex Blair over 6 years
    Could you be more specific?