Reputation: 2653
For part of the application that I'm working on involves a series of timers stored in an object array. Ideally, I would like to iterate through this array, get the duration for the timer and proceed to countdown. Once the timer has finished, go to the next item in the array and repeat the process
for(index, content) in enumerate timerList{
doneTimer = NSTimer.scheduledTimerWithTimeInterval(timerList[index].duration, target: self, selector: Selector("finished:"), userInfo: nil, repeats: false)
}
func finished(timer : NSTimer){
//do whatever and tell the loop to get the next item?
}
What is the best way to put this for loop "on hold" until the timer finishes before going to the next item in the array?
Upvotes: 0
Views: 1103
Reputation: 41226
In any kind of GUI application, one of the basic rules is you never want to "pause" or "stop" or "wait." Instead, what you want to do is start an operation that will finish sometime later, go back to the GUI, and then when that operation finishes, pick up where you left off.
In the context of your question, it seems like what you're trying to do is find the nearest timer, start it up, display some stuff in the GUI, and then not do anything until the timer has fired.
With that in mind, the basic model you want to take is to find the earliest timer, start it up, display something in the GUI, and then go back to the system. When that timer fires, then you can repeat the process.
With a lot of vagueness in your original question, what you're going to wind up with is something like:
class TimerController {
var timers = [Timer]()
var runningTimer : NSTimer?
var countDownDisplay : UILabel?
class Timer {
let fireDate : NSDate
init(fireDate:NSDate) {
self.fireDate = fireDate
}
}
// given an array of NSTimer, find the earliest one to fire
func findEarliestTimer() -> Timer? {
return timers.sorted( { return $0.fireDate.timeIntervalSince1970 < $1.fireDate.timeIntervalSince1970 } ).first
}
func scheduleEarliestTimer() {
runningTimer?.invalidate()
runningTimer = nil
if let timer = findEarliestTimer() {
let duration = min(1.0, timer.fireDate.timeIntervalSinceNow)
runningTimer = NSTimer.scheduledTimerWithTimeInterval(duration, target: self, selector: "finish", userInfo: timer, repeats: false)
}
}
func finish(nstimer:NSTimer) {
let timer = nstimer.userInfo as Timer
// update the gui countdown
self.countDownDisplay?.text = "\(floor(timer.fireDate.timeIntervalSinceNow))"
// remove timer
timers = timers.filter { $0 !== timer }
// schedule the next timer
self.scheduleEarliestTimer()
}
}
Note that I'm using NSDate to hold when the timer goes off rather than duration, because "duration" only has significance when the start point is known. If you want a string of operations with a fixed duration to fire consecutively, modify as appropriate.
Since you're wanting to show some kind of countdown, you'll want to modify the NSTimer to fire every second until the appropriate time, each time it fires update the countdown.
Upvotes: 1