Home > OS >  How to fire multiple different timers in a synchronous way?
How to fire multiple different timers in a synchronous way?

Time:04-01

I want to build an App where the user does exercises in a row following a timer. He can decide the nb of timers and the value of each timer. It works well for one timer but when I have more than one I would like to fire them in a serial mode (fire timer1 and only when finished fire timer2, etc). Here the code and what I see is that the timers are fired asynchronously one after the other before the previous ends. I spend quite some time to find a simple way to code it (I am not sure that synchronous queues are needed). I checked many questions but couldn't find a similar response. Any clue how to do it?

@IBOutlet weak var timerLabel: UILabel!

var timer = Timer()
var myTimers = [5, 10, 8]
var myTimeCheck = 0
var seconds = 0

@IBAction func launchTimersPressed(_ sender: UIButton) {

    for myTime in myTimers {
        
        let queue = DispatchQueue(label:"com.queue.serial")
        
        queue.sync {
            timer = Timer.scheduledTimer(timeInterval: 1, target: self, selector: #selector(self.updateChrono), userInfo: nil, repeats: true)
            
            print ("myTime = \(myTime)")
            myTimeCheck = myTime
        }
    }
}

@objc func updateChrono() {
    
    seconds  = 1
    timerLabel.text = "\(seconds)"
    
    // checking if we arrive at end of time
    print("seconds and myTime: \(seconds) and \(myTimeCheck) ")
    if seconds == myTimeCheck {
        
        timer.invalidate()
        return     // to move out
    }
}

CodePudding user response:

Don't try and run timers in a synchronous queue. That's silly.

It looks like all your timers fire every second, and always invoke the same target. So just have one timer that runs constantly. It will be a "check the state of the current exercise" timer.

Have a var hold an array of Doubles that indicates the number of seconds for each exercise. Better yet, have an array of structs representing exercises.

When the user starts an exercise, remove its struct from the array and save it in a variable currentExercise.

When the user begins a specific exercise, also compute an exerciseCompletedTime TimeInterval.

Each time your once-a-second timer fire, see if the current time is ≥ exerciseCompletedTime. If it is, mark that exercise as completed, remove the next exercise struct from the array of exercises, set that one up as the current exercise, and compute a new exerciseCompletedTime.

  • Related