Reputation: 776
I have multiple views each associated with its own timer. However, only one view is running a time each time. I am accessing each view in a for ... in loop and if the previous timer in the previous view has stopped, which I invalidate in the selector method, I want to fire the time for the next view.
the code looks like this:
var timer = NSTimer()
let timeInterval:NSTimeInterval = 1
var views = [TimerView]()
var timeCountDown: NSTimeInterval = 0
override func viewDidLoad() {
//viewDidLoad create the necessary UIView and fill the views array then pass them to a call to startTimer:
startTimer(views)
}
//startTimer function create the countdown timer
func startTimer(timerViews: [TimerView]){
for timerView in timerViews {
if !timer.valid { // a view with its associated timer start only when the previous timer has run its course and is invalidated
//creating a timer to associate with the current view
timer = NSTimer.scheduledTimerWithTimeInterval(timeInterval,
target: self,
selector: "timerDidEnd:",
userInfo: timerView,
repeats: true)
}
}
}
//Callback function
func timerDidEnd(timer: NSTimer){
let timerView = timer.userInfo as! TimerView
timeCountDown = timeCountDown - timeInterval
timerView.timeLabel.text = timeToString(timeCountDown)
timerView.curValue = CGFloat(timeCountDown)
if timeCount <= 0.0 {
resetTimeCount()
}
}
func timeToString(time:NSTimeInterval) -> String {
let minutes = Int(time) / 60
let seconds = time - Double(minutes) * 60
return String(format:"%02i:%02i",minutes,Int(seconds))
}
func resetTimeCount(){
timer.invalidate()
}
With some print debugging for three views I am getting this output: "running the for loop", "calling view #1 by for loop", "calling the timer", "calling view #2 by for loop", "calling view #3 by for loop","countdown starting" ... That is the countdown only start after the for loop has terminated.
the problem I have is that the first timer run while the for loop calls all the views in my view array. How do I get the for loop to wait for the timer to be invalidated before it iterates to the next view?
What I am trying to achieve is this: the first view starts a countdown; when that countdown finished a second appears and run a countdown as well. Then the third view with a new countdown and so on until the last view. But it looks like the for loop in my code finish looping before the first timer associated with the first view in the collection actually starts
thanks
edit: I am wondering if the timer is not running on a different thread than the for loop?
Upvotes: 2
Views: 1556
Reputation: 131418
Your code has a logic problem. It looks like you have a single instance variable, timer
. Your for loop starts, and on the first pass, presumably timer
is not valid. So you overwrite it with a new timer that IS valid. Now on the second pass through the array of timerViews
, you check the same shared timer
instance variable, but this time (And all subsequent times) timer
is valid, so the body of the if statement doesn't fire.
If you really want a separate timer for each view then you will need to store all those timers. One way would be to have an array of timers that goes along with your array timerViews. Or you could create an array of tuples where each element contains a view and it's associated timer.
Stepping back from your problem, though, why do you want a separate timer for each field? Why not have a single timer, and each time it fires, loop through the array of fields and decide what you need to do with each one? You could have an array of structs that contains references to your views plus status information that lets your loop decide what to do with each one.
Upvotes: 1