Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Swift Timer Problems

Tags:

swift

timer

I'm doing a game in which there are many rounds, and each round, the timer resets to zero. This is my code for when I get it correct:

func correct() {
    time = 10
    timer()
    //bla bla bla
}

And this is the code for the timer:

func timer() {
    let delayTime = dispatch_time(DISPATCH_TIME_NOW, Int64(1 * Double(NSEC_PER_SEC)))
    dispatch_after(delayTime, dispatch_get_main_queue()) {
        self.time -= 1
        if self.time > 0 {
            self.timer()
        } else {
            self.dismissViewControllerAnimated(true, completion: nil)
        }
    }

}

I had expected the timer to reset to 10 and tick every second normally, but instead, it went back to ten, but it was counting down really quickly. For example, by round three, it was counting like 10, 9, 7, 6, and each number only lasted about half a second. Can you please tell me how to fix it if possible please? Thanks!

UPDATE: Apparently, my problem was that I was running multiple timers at once. I need be able to replace the original timer with the new one, or at least stop the original. I've searched it up and found .invalidate(), but I'm not sure how to use it. If that's the method I should use, then how should I use it? Thanks!

like image 935
sw2037122 Avatar asked Feb 11 '26 18:02

sw2037122


1 Answers

There are various ways to do what you want to do, using a NSTimer is probably the best solution. You can use either a repeating timer (will be invoked repeatedly after an interval) or one without repeating (you will have to reschedule it for every iteration).

The bonus of using a timer instead of dispatch_after is the fact that you can easily cancel (invalidate) a timer, thus avoiding conflicting timers.

Using a timer without repeating:

var timer: NSTimer?
var time: Int = 0

func correct() {
    time = 10

    //this will remove the previous timer
    timer?.invalidate()
    startTimer()
}

func startTimer() {
    timer = NSTimer.scheduledTimerWithTimeInterval(1.0, target: self, selector: "onTimerFired", userInfo: nil, repeats: false)
}

func onTimerFired() {
    time -= 1

    if self.time > 0 {
        startTimer()
    } else {
        self.dismissViewControllerAnimated(true, completion: nil)
    }
}

Using a timer with repeating:

var timer: NSTimer?
var time: Int = 0

func correct() {
    time = 10

    //this will remove the previous timer
    timer?.invalidate()
    startTimer()
}

func startTimer() {
    timer = NSTimer.scheduledTimerWithTimeInterval(1.0, target: self, selector: "onTimerFired", userInfo: nil, repeats: true)
}

func onTimerFired() {
    time -= 1

    if time == 0 {
        //need to remove the timer here otherwise it would keep repeating
        timer!.invalidate()
        self.dismissViewControllerAnimated(true, completion: nil)
    }
}

Of course, you can also just use the already running timer, just check if timer != nil && timer!.valid and don't start a new one if the condition is true.

like image 161
Sulthan Avatar answered Feb 13 '26 15:02

Sulthan



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!