In this tutorial, we’ll be discussing and implementing the Timer class. We’ll be developing an iOS Application which runs a Countdown Timer.
Timer
A Timer class is that fires a method at certain intervals.
To create a Timer:
1 2 |
Timer.scheduledTimer(timeInterval: 1, target: self, selector: (#selector(ViewController.updateTimer)), userInfo: nil, repeats: true) |
The above timer runs every second. The function passed in the selector gets triggered on every timeInterval.
Setting repeats
to false would imply that the timer would be fired just once.
A nonrepeating timer fires once and then invalidates itself automatically.
Timer class has replaced the earlier NSTimer class in Swift.
UserInfo
is where we can pass some extra data which can be retrieved from the Timer instance later on.
1 2 3 4 |
let context = ["user": "@anupam"] Timer.scheduledTimer(timeInterval: 1.0, target: self, selector: #selector(myTimer), userInfo: context, repeats: true) |
1 2 3 4 5 6 7 |
@objc func myTimer(timer: Timer) { guard let context = timer.userInfo as? [String: String] else { return } let user = context["user", default: "NA"] print("Timer fired by (user)!") } |
The data passed inside the UserInfo is a Dictionary.
To stop a Timer we can simply call:
1 2 3 |
timer.invalidate() |
invalidate()
stops the Timer from firing again and removes the Timer from the running loop.
Instead of adding a selector function which gets triggered, we can use a closure to run the desired action whenever the Timer is fired.
1 2 3 4 5 |
_ = Timer.scheduledTimer(withTimeInterval: 5, repeats: false) { timer in label.isHidden = true } |
In the next section, we’ll be creating a Countdown Timer iOS Application with play/pause/reset buttons.
Also, we’ll format the time to show the hours, minutes, seconds properly in the Label.
Project Storyboard
Connect the IBOutlet for the Buttons and Label and the IBAction for the Buttons to the ViewController using Control and Drag.
Code
The code for the ViewController.swift is given below:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 |
import UIKit class ViewController: UIViewController { @IBOutlet weak var myLabel: UILabel! @IBOutlet weak var playButton: UIButton! @IBOutlet weak var pauseButton: UIButton! var seconds = 60 var timer = Timer() var hasTimerStarted = false var isResumed = false override func viewDidLoad() { super.viewDidLoad() self.pauseButton.isEnabled = false } func runTimer() { timer = Timer.scheduledTimer(timeInterval: 1, target: self, selector: (#selector(ViewController.updateTimer)), userInfo: nil, repeats: true) self.pauseButton.isEnabled = true } @objc func updateTimer() { if seconds String { let hours = Int(time) / 3600 let minutes = Int(time) / 60 % 60 let seconds = Int(time) % 60 return String(format:"%02i:%02i:%02i", hours, minutes, seconds) } @IBAction func playClicked(_ sender: Any) { if hasTimerStarted == false { runTimer() self.playButton.isEnabled = false } } @IBAction func pauseClicked(_ sender: Any) { if self.isResumed == false { timer.invalidate() hasTimerStarted = false self.isResumed = true self.pauseButton.setTitle("Resume",for: .normal) } else { runTimer() self.isResumed = false hasTimerStarted = true self.pauseButton.setTitle("Pause",for: .normal) } } @IBAction func resetClicked(_ sender: Any) { timer.invalidate() seconds = 360 myLabel.text = formattedTime(time: TimeInterval(seconds)) hasTimerStarted = false isResumed = false self.pauseButton.setTitle("Pause",for: .normal) pauseButton.isEnabled = false self.playButton.isEnabled = true } } |
The formattedTime
function is where we format the time to be displayed on the label.
We need to carefully toggle the Pause button text and keep a flag on it to check its current state.
When the Reset Button is clicked, everything is stopped and reset with a new countdown of 6 minutes.
The output of the application in action is given below:
This brings an end to this tutorial. You can download the project from the link below: