How to Add a Countdown Timer with Day + Hour + Minute + Second In 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
- Scenario B: When You Just Want to Countdown By X Hours / Minutes / Seconds
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!