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)
}

      

+3


source to share


4 answers


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()
}

      

+1


source


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 as Timer()

    does nothing useful. It would be wiser if it timer

    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 button isEnabled

    .
+3


source


I think you need to invalidate if the timer is running

@IBAction func start(_ sender: AnyObject) {
    if (timer) {
        timer.invalidate()
    } 
    timer = Timer.scheduledTimer(timeInterval: 1, target: self, selector: #selector(ViewController.action), userInfo: nil, repeats: true)
}

      

0


source


@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)
    }
}

      

0


source







All Articles