Reputation: 519
I have a problem with invalidating different timers.
I have multiple timers (NSTimer
) on a viewcontroller(settingsVC):
class settingsVC: UIViewController {
// I use 12 timers
var timer1 = NSTimer()
// Seconds to end the timer. Set 12 timers
let timeInterval1:NSTimeInterval = 10
var timer2 = NSTimer()
let timeInterval2:NSTimeInterval = 20
var timer3 = NSTimer()
let timeInterval3:NSTimeInterval = 30
//and so on ... 12 timers
}
With a UIButton
(Start) a segue is performed. And for every different value of the variable 'picked', a different timer will be started in the same class:
class settingsVC: UIViewcontroller {
let defaults = NSUserDefaults.standardUserDefaults()
let pickerDefaultsIntegerKey = "Picker" // nsuserdefaults key
@IBAction func start(sender: AnyObject) {
// segue to another viewcontroller
performSegueWithIdentifier("timerOn", sender: self)
if picked == 1 {
defaults.setInteger(1, forKey: pickerDefaultsIntegerKey)
timer1 = NSTimer.scheduledTimerWithTimeInterval(timeInterval1,
target: self,
selector: "timerDidEnd:",
userInfo: nil,
repeats: false)
print("timer1 started")
} else if picked == 2 {
defaults.setInteger(2, forKey: pickerDefaultsIntegerKey)
timer2 = NSTimer.scheduledTimerWithTimeInterval(timeInterval2,
target: self,
selector: "timerDidEnd:",
userInfo: nil,
repeats: false)
print("timer2 started")
} else if // ....and so on{........ }
}
The method fired if timer ends, see selector:
func timerDidEnd(timer:NSTimer){
print("timer ended")
// do other stuff
}
I invalidate the timers with a button (Reset) for values from a variable ('pickerSavedSelection') which is updated by saved values in NSUserdefaults:
@IBAction func reset(sender: AnyObject) {
if let pickerSavedSelection = defaults.integerForKey(pickerDefaultsIntegerKey) as Int?
{
if pickerSavedSelection == 1 {
timer1.invalidate()
} else if pickerSavedSelection == 2 {
timer2.invalidate()
} else if //...and so on{....}
}
All goes well, if I outcomment the perform segue
line and just let the user stay on this viewcontroller.The timers get invalidated correctly then:
In the console I read 'timer1 started' and I do NOT read 'timer ended' when the resetButton is pressed.
But staying on this viewcontroller(settingsVC) is NOT the flow of my app.
When the perform segue
line is executed and the user 'comes back' to the viewcontroller (settingsVC), the timers are not invalidated when user presses the resetButton:
In the console I read 'timer1 started' and I DO read 'timer ended' when the resetButton is pressed.
How should I stop the timers, when users will 'exit' the viewcontroller and come back to reset the timers?
Help is much appreciated! Thanks in advance
Upvotes: 1
Views: 522
Reputation: 38142
If I am not mistaken at any given point in time, you are only triggering one NSTimer
. All your different timers are differentiated only in time intervals. So, my suggestion would be to keep only one NSTimer
and have your time interval differentiated. With different value picked you should first invalidate the timer and then restart it with new time interval. That said, your reset
will then be much simplified and you do not need to save pickerSavedSelection
in NSUserDefaults
. This is how I would re-write this code:
class settingsVC: UIViewController {
var timer = NSTimer()
@IBAction func start(sender: AnyObject) {
// segue to another viewcontroller
performSegueWithIdentifier("timerOn", sender: self)
if picked == 1 {
self.timer.invalidate()
self.timer = NSTimer.scheduledTimerWithTimeInterval(10,
target: self,
selector: "timerDidEnd:",
userInfo: nil,
repeats: false)
print("timer1 started")
} else if picked == 2 {
self.timer.invalidate()
self.timer = NSTimer.scheduledTimerWithTimeInterval(20,
target: self,
selector: "timerDidEnd:",
userInfo: nil,
repeats: false)
print("timer2 started")
} else if // ....and so on{........ }
}
@IBAction func reset(sender: AnyObject) {
self.timer.invalidate()
}
}
PS: As a side note, I would advise your NSTimer
to start & stop from main thread. Use GCD for that.
Upvotes: 1
Reputation: 1792
It is because your selector is not called when your timer is invalidated, it is called everytime your timer is fired. Since the timer is non-repeat, the selector get called only once. When your press reset button, timer is actually invalidated, you just didn't know because you misunderstood scheduledTimerWithTimeInterval:target:selector:userInfo:repeats:
method.
Upvotes: 0