Last updated on: May 27, 2023
Today, I will show how to build a timer that countdowns until an event (e.g. new year’s day or the release date of a video game) using the scheduledTimer of the Timer class and refresh it every second.
First, we set the current date using the calendar that users use on their device.
class ViewController: UIViewController {
@IBOutlet var timerLabel: UILabel!
override func viewDidLoad() {
super.viewDidLoad()
// ...
}
@objc func UpdateTime() {
let userCalendar = Calendar.current
// Set Current Date
let date = Date()
let components = userCalendar.dateComponents([.hour, .minute, .month, .year, .day, .second], from: date)
let currentDate = userCalendar.date(from: components)!
// ...
}
}
Code language: Swift (swift)
We set the event time we want:
class ViewController: UIViewController {
@IBOutlet var timerLabel: UILabel!
override func viewDidLoad() {
super.viewDidLoad()
// ...
}
@objc func UpdateTime() {
// ...
// Set Event Date
var eventDateComponents = DateComponents()
eventDateComponents.year = 2021
eventDateComponents.month = 01
eventDateComponents.day = 01
eventDateComponents.hour = 00
eventDateComponents.minute = 00
eventDateComponents.second = 00
eventDateComponents.timeZone = TimeZone(abbreviation: "GMT")
}
}
Code language: Swift (swift)
If an event is happening at a particular time (e.g. a tv show starts at 8:00PM GMT) we can add the time zone alongside the date of this event.
We convert the event date to the user’s calendar:
class ViewController: UIViewController {
@IBOutlet var timerLabel: UILabel!
override func viewDidLoad() {
super.viewDidLoad()
// ...
}
@objc func UpdateTime() {
let userCalendar = Calendar.current
// ...
// Convert eventDateComponents to the user's calendar
let eventDate = userCalendar.date(from: eventDateComponents)!
}
}
Code language: Swift (swift)
We change the seconds to days, hours, minutes and seconds:
class ViewController: UIViewController {
@IBOutlet var timerLabel: UILabel!
override func viewDidLoad() {
super.viewDidLoad()
// ...
}
@objc func UpdateTime() {
let userCalendar = Calendar.current
// ...
// Change the seconds to days, hours, minutes and seconds
let timeLeft = userCalendar.dateComponents([.day, .hour, .minute, .second], from: currentDate, to: eventDate)
}
}
Code language: Swift (swift)
…and we display the results into our label:
class ViewController: UIViewController {
@IBOutlet var timerLabel: UILabel!
override func viewDidLoad() {
super.viewDidLoad()
// ...
}
@objc func UpdateTime() {
// ...
// Display Countdown
timerLabel.text = "\(timeLeft.day!)d \(timeLeft.hour!)h \(timeLeft.minute!)m \(timeLeft.second!)s"
}
}
Code language: Swift (swift)
Last, we add the Timer in our viewDidLoad(), and set it to repeat the method every second:
class ViewController: UIViewController {
@IBOutlet var timerLabel: UILabel!
var timer: Timer!
override func viewDidLoad() {
super.viewDidLoad()
timer = Timer.scheduledTimer(timeInterval: 0.1, target: self, selector: #selector(UpdateTime), userInfo: nil, repeats: true) // Repeat "func Update() " every second and update the label
}
@objc func UpdateTime() {
// ...
}
}
Code language: Swift (swift)
If you want to change the label after the event has passed, you can do this by checking if the current date is after the event. If yes, then will stop the timer and show the text.
class ViewController: UIViewController {
@IBOutlet var timerLabel: UILabel!
var timer: Timer!
override func viewDidLoad() {
super.viewDidLoad()
// ...
}
@objc func UpdateTime() {
// ...
// Show diffrent text when the event has passed
endEvent(currentdate: currentDate, eventdate: eventDate)
}
func endEvent(currentdate: Date, eventdate: Date) {
if currentdate >= eventdate {
timerLabel.text = "Happy New Year!"
// Stop Timer
timer.invalidate()
}
}
}
Code language: Swift (swift)
So at the end, our ViewController looks like this:
class ViewController: UIViewController {
@IBOutlet var timerLabel: UILabel!
var timer: Timer!
override func viewDidLoad() {
super.viewDidLoad()
timer = Timer.scheduledTimer(timeInterval: 0.1, target: self, selector: #selector(UpdateTime), userInfo: nil, repeats: true) // Repeat "func Update() " every second and update the label
}
@objc func UpdateTime() {
let userCalendar = Calendar.current
// Set Current Date
let date = Date()
let components = userCalendar.dateComponents([.hour, .minute, .month, .year, .day, .second], from: date)
let currentDate = userCalendar.date(from: components)!
// Set Event Date
var eventDateComponents = DateComponents()
eventDateComponents.year = 2020
eventDateComponents.month = 01
eventDateComponents.day = 01
eventDateComponents.hour = 00
eventDateComponents.minute = 00
eventDateComponents.second = 00
eventDateComponents.timeZone = TimeZone(abbreviation: "GMT")
// Convert eventDateComponents to the user's calendar
let eventDate = userCalendar.date(from: eventDateComponents)!
// Change the seconds to days, hours, minutes and seconds
let timeLeft = userCalendar.dateComponents([.day, .hour, .minute, .second], from: currentDate, to: eventDate)
// Display Countdown
timerLabel.text = "\(timeLeft.day!)d \(timeLeft.hour!)h \(timeLeft.minute!)m \(timeLeft.second!)s"
// Show diffrent text when the event has passed
endEvent(currentdate: currentDate, eventdate: eventDate)
}
func endEvent(currentdate: Date, eventdate: Date) {
if currentdate >= eventdate {
timerLabel.text = "Happy New Year!"
// Stop Timer
timer.invalidate()
}
}
}
Code language: Swift (swift)
You can find the final project here
If you have any questions, please feel free to leave a comment below