Countdown in seconds only (form 00:20 to 0) using NSTimer

1k views Asked by At

I need to have a label countdown from 20secs to 0 and start over again. This is my first time doing a project in Swift and I am trying to use NSTimer.scheduledTimerWithTimeInterval. This countdown should run in a loop for a given amount of times.

I am having a hard time implementing a Start and Start again method (loop). I basically am not finding a way to start the clock for 20s and when it's over, start it again.

I'd appreciate any idea on how to do that Wagner

 @IBAction func startWorkout(sender: AnyObject) {

    timer = NSTimer.scheduledTimerWithTimeInterval(0.01, target: self, selector: Selector("countDownTime"), userInfo: nil, repeats: true)
    startTime = NSDate.timeIntervalSinceReferenceDate()

}

func countDownTime() {

    var currentTime = NSDate.timeIntervalSinceReferenceDate()

    //Find the difference between current time and start time.
    var elapsedTime: NSTimeInterval = currentTime - startTime

    //calculate the seconds in elapsed time.
    let seconds = UInt8(elapsedTime)
    elapsedTime -= NSTimeInterval(seconds)

    //find out the fraction of milliseconds to be displayed.
    let fraction = UInt8(elapsedTime * 100)

    //add the leading zero for minutes, seconds and millseconds and store them as string constants
    let strSeconds = seconds > 9 ? String(seconds):"0" + String(seconds)
    let strFraction = fraction > 9 ? String(fraction):"0" + String(fraction)

    //concatenate minuets, seconds and milliseconds as assign it to the UILabel
    timeLabel.text = "\(strSeconds):\(strFraction)"
}
4

There are 4 answers

0
Leo Dabus On BEST ANSWER

You should set your date endTime 20s from now and just check the date timeIntervalSinceNow. Once the timeInterval reaches 0 you set it 20 seconds from now again

import UIKit

class ViewController: UIViewController {

    @IBOutlet weak var strTimer: UILabel!

    var endTime = Date(timeIntervalSinceNow: 20)
    var timer = Timer()

    @objc func updateTimer(_ timer: Timer) {
        let remaining = endTime.timeIntervalSinceNow
        strTimer.text = remaining.time
        if remaining <= 0 {
            endTime += 20
        }
    }

    override func viewDidLoad() {
        super.viewDidLoad()
        strTimer.font = .monospacedSystemFont(ofSize: 20, weight: .semibold)
        strTimer.text =  "20:00"
        timer = .scheduledTimer(timeInterval: 1/30, target: self, selector: #selector(updateTimer), userInfo: nil, repeats: true)
    }

}

extension TimeInterval {
    var time: String {
        String(format: "%02d:%02d", Int(truncatingRemainder(dividingBy: 60)), Int((self * 100).truncatingRemainder(dividingBy: 100)))
    }
}
0
chrisamanse On

In your countdownTime(), change your startTime to current time when your elapsed time reaches 20 seconds

0
mkko On

First of all, if you're simply looping without stopping, you could just use module to get the seconds. That is seconds % 20 would just jump from 19.9 to 0.0. And thus, if your counting down, you would calculate seconds - seconds % 20 which would jump to 20 when it reached zero. Over and over again. Is this what you're after?

For the leading zeros you can use: String(format: "%02d:%02d", seconds, fraction). Please note the formatting: here seconds and fraction are integer numbers.

But if you need to stop the timer, you have to keep track of the previously counted seconds and reset the startTime at each start. Every time you stop, you'd have to add up the current seconds to previously counted seconds. Am I making any sense?

0
Michael Steele On

To minimize processing, you could create two timers. One timer for 20 seconds and another timer for how often you want to update the UI. It would be difficult to see 100 frames per second. If you are checking every 0.01, your code is less accurate. The manual is really helpful. https://developer.apple.com/library/mac/documentation/Cocoa/Reference/Foundation/Classes/NSTimer_Class/ When you no longer have use of the timer invalidate and set to nil. Other timing functions exist also.