Swift Timer App
I was trying to create a simple ios timer app using swift3. I have successfully created an application using the following code. It has three buttons, one to start the timer, one to stop the timer, which means reset, and one to pause the timer. all buttons work, but when I press start again while the timer is running, the timer interval speeds up (meaning the selector function twice in a second). How to solve this problem. Here is my code
@IBOutlet weak var lbl: UILabel!
var time = 0
var timer = Timer()
@IBOutlet weak var start: UIButton!
@IBOutlet weak var stop: UIButton!
@IBOutlet weak var pause: UIButton!
@IBAction func start(_ sender: AnyObject) {
timer = Timer.scheduledTimer(timeInterval: 1, target: self, selector: #selector(ViewController.action), userInfo: nil, repeats: true)
}
@IBAction func stop(_ sender: AnyObject) {
//timer.invalidate()
time = 0
lbl.text = "0"
}
@IBAction func pause(_ sender: AnyObject) {
timer.invalidate()
}
override func viewDidLoad() {
super.viewDidLoad()
}
func action() {
time += 1
lbl.text = String(time)
}
source to share
One mistake in the source code.
Stop the timer first, then start a new timer.
The code for this is below.
@IBAction func start(_ sender: AnyObject) {
timer.invalidate()
timer = Timer.scheduledTimer(timeInterval: 1, target: self, selector: #selector(ViewController.action), userInfo: nil, repeats: true)
}
And for the stop timer, use an invalid timer function.
@IBAction func stop(_ sender: AnyObject) {
timer.invalidate()
}
source to share
If your method start
runs when the timer is already active, you create a second timer. You now have two timers that trigger the same action, which explains your problem. Scheduled timers are saved with start cycles, so even if you don't have a reference to the old timer, it's still there.
At a minimum, you need to either invalidate the old timer or just keep using the one you have. But there are some things that can help make the code better:
- The attribute
timer
must be optional. Initializing it asTimer()
does nothing useful. It would be wiser if ittimer
could be zero when the timer shouldn't be running. - You should probably disable your "start" button when the timer starts. It doesn't make sense for it to be active when the timer is already running. You can do this by setting for the button
IBOutlet
and changing the value if the property of the buttonisEnabled
.
source to share
@IBOutlet weak var lbl: UILabel!
var time = 0
var timer : Timer?
var isPause = false
@IBOutlet weak var start: UIButton!
@IBOutlet weak var stop: UIButton!
@IBOutlet weak var pause: UIButton!
@IBAction func start(_ sender: AnyObject) {
timer?.invalidate()
timer = nil
isPause = false
time = 0
lbl.text = "0"
// or call stop(self.stop)
timer = Timer.scheduledTimer(timeInterval: 1, target: self, selector: #selector(ViewController.action), userInfo: nil, repeats: true)
}
@IBAction func stop(_ sender: AnyObject) {
timer?.invalidate()
timer = nil
isPause = false
time = 0
lbl.text = "0"
}
@IBAction func pause(_ sender: AnyObject) {
timer.invalidate()
isPause = !isPause // second click to resum...
}
override func viewDidLoad() {
super.viewDidLoad()
}
func action() {
if !isPause {
time += 1
lbl.text = String(time)
}
}
source to share