How to Add a Countdown Timer with Day + Hour + Minute + Second In Swift

Jian Jye • April 2, 2016

ios swift

There are various reasons why one would want a countdown timer. In my case, I wanted a countdown timer to display the time left before an auction closes. Naturally, I searched for available packages that I could use instantly first. And I found MZTimerLabel.

It is a pretty handy package. Lots of websites have recommended it even. Almost perfect for my use case… But then I discovered that if I choose to display the day info, MZTimerLabel will always show an extra day. A few users have reported that bug. No response.

Plan B

Obviously having a wrong day displayed is a deal breaker. For my plan b, I have no choice but to come up with my own solutions since I can’t find any other package to use.

To my surprise, it is extremely easy!


Solution in Swift

There are two scenarios here:

Scenario A: When You Are Counting Down to a Deadline

If you have an deadline that you need to count to, this method takes the deadline as a UNIX Timestamp input and starts the timer for you.

@IBOutlet weak var timeLeftLabel: UILabel! 

var timeEnd: NSDate!

func updateView() { 
    // Initialize Label
    timeEnd = NSDate(timeIntervalSince1970: timestamp)
    setTimeLeft()

    // Start timer 
    NSTimer.scheduledTimerWithTimeInterval(1.0, target: self, selector: #selector(self.setTimeLeft), userInfo: nil, repeats: true) 
} 

func setTimeLeft() { 
    let timeNow = NSDate()

    // Only keep counting if timeEnd is bigger than timeNow
    if timeEnd.compare(timeNow) == NSComparisonResult.OrderedDescending {
        let calendar = NSCalendar.currentCalendar() 
        let components = calendar.components([.Day, .Hour, .Minute, .Second], fromDate: timeNow, toDate: timeEnd, options: []) 

        var dayText = String(components.day) + "d " 
        var hourText = String(components.hour) + "h " 

        // Hide day and hour if they are zero 
        if components.day <= 0 { 
            dayText = "" 
            if components.hour <= 0 { 
                hourText = "" 
            } 
        } 
        timeLeftLabel.text = dayText + hourText + String(components.minute) + "m " + String(components.second) + "s"

    } else {
        timeLeftLabel.text = "Ended"
    } 
}

Scenario B: When You Just Want to Countdown By X Hours / Minutes / Seconds

With slight modifications of our previous codes, we can make it work for Scenario B too.

@IBOutlet weak var timeLeftLabel: UILabel! 

// Counting down to 10 hours, converted to seconds
let timeEnd = NSDate(timeInterval: 10*60*60, sinceDate: NSDate())

func updateView() { 
    // Initialize the label 
    setTimeLeft() 

    // Start timer 
    NSTimer.scheduledTimerWithTimeInterval(1.0, target: self, selector: #selector(self.setTimeLeft), userInfo: nil, repeats: true) 
} 

func setTimeLeft() { 
    let timeNow = NSDate()

    // Only keep counting if timeEnd is bigger than timeNow
    if timeEnd.compare(timeNow) == NSComparisonResult.OrderedDescending {
        let calendar = NSCalendar.currentCalendar() 
        let components = calendar.components([.Day, .Hour, .Minute, .Second], fromDate: timeNow, toDate: timeEnd, options: []) 

        var dayText = String(components.day) + "d " 
        var hourText = String(components.hour) + "h " 

        // Hide day and hour if they are zero 
        if components.day <= 0 { 
            dayText = "" 
            if components.hour <= 0 { 
                hourText = "" 
            } 
        } 
        timeLeftLabel.text = dayText + hourText + String(components.minute) + "m " + String(components.second) + "s"

    } else {
        timeLeftLabel.text = "Ended"
    } 
}

That's all!

Sign up for our newsletter