Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Timer.scheduledTimer not firing

I am trying to calculate the time it takes a vehicle to go between two checkpoints. I have setup the following timer to achieve this.

func startTimer() {
    if hasStarted == true && timerStarted == false {
        print("Timing started!")
        gameTimer = Timer.scheduledTimer(timeInterval: 0.001, target: self, selector: (#selector(activeTiming)), userInfo: nil, repeats: true)
        timerStarted = true
    }
}

@objc func activeTiming() {
    print("Active timing block")
    if(hasFinished == false) {
        gameTime = gameTime + 0.001
        print("Add time succeeded")
    } else {
        gameTimer?.invalidate()
    }
}

The expected output would be the following:

Timing started!
Active timing block
Add time succeeded
Add time succeeded ... etc

The actual output:

Timing started!

So it would appear that the startTimer is properly being called but the timer is not firing the activeTiming block of code. Any suggestions would be extremely helpful. Thank you for your help in advance.

like image 923
Colton Wagner Avatar asked Mar 02 '26 23:03

Colton Wagner


2 Answers

I also faced a similar issue where the timer body was not getting called. I found out that the timer was getting scheduled from a background thread instead of the main thread. Wrapping it in DispatchQueue.main.async fixed it.

DispatchQueue.main.async {
    self.pingTimer = Timer.scheduledTimer(withTimeInterval: timerInterval, repeats: true, block: { [weak self] timer in
        //
        Logger.shared.log(.anyCable, .debug, "timer run")
        self?.sendPing(sender: self)
    })
}
like image 106
Abdullah Umer Avatar answered Mar 04 '26 14:03

Abdullah Umer


Posting this code as it is what I'm using, but I’m no expert on Swift, so your mileage may vary!

class PerformanceTest {
    var name:           String = ""
    var tolerance:      Int64 = 0
    var lastTime:       Int64 = 0
    var thisTime:       Int64 = 0
    var delta:          Int64 = 0
    var percent:        Float = 0

    func setTolerance(vName: String, vTolerance: Int64) {
        name = vName
        tolerance = vTolerance
    }

    func reset() {
        delta = 0
        percent = Float((Float(delta) / Float(tolerance))) * 100
        //high = 0
    }

    func start() {
        lastTime = Date().toMillis()
    }

    func finish() {
        thisTime = Date().toMillis()
        let vDelta = thisTime - lastTime
        if(vDelta > delta) {
            delta = vDelta
            percent = Float((Float(delta) / Float(tolerance))) * 100
            if(delta > tolerance) {
                print("Performance Indicator: \(name) Above Tolerance" + String(format: "%3.0f", percent) + "%")
            }
        }
    }

    func display() -> String {
        //high = delta
        //print("\(vString) Tolerance: \(tolerance) Max: \(high)")
        return String(format: "%3.0f", percent) + "%  |"
    }
   }

extension Date {
    func toMillis() -> Int64! {
        return Int64(self.timeIntervalSince1970 * 1000)
    }

Usage:

var performanceDefenseLoop = PerformanceTest()
performanceDefenseLoop.setTolerance(vName:  "DefenseLoop", vTolerance: 150)

func timeToUpdateDefenses()
{
    performanceDefenseLoop.start()
    defesensesLoop()
    performanceDefenseLoop.finish()
    print("\(performanceDefenseLoop.Display())"
}

// To reset performanceDefenseLoop.reset()

Be sure to start timers in the main thread!

like image 36
Voltan Avatar answered Mar 04 '26 13:03

Voltan