Filed Under: iOS

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:


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.


let context = ["user": "@anupam"]
Timer.scheduledTimer(timeInterval: 1.0, target: self, selector: #selector(myTimer), userInfo: context, repeats: true)

@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:


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.


 _ = 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

ios timer 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:


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 < 1 {
            timer.invalidate()
        } else {
            seconds -= 1
            myLabel.text = formattedTime(time: TimeInterval(seconds))
        }
    }

    
    func formattedTime(time:TimeInterval) -> 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:

ios timer output

This brings an end to this tutorial. You can download the project from the link below:

Comments

  1. Pratik Patil says:

    how can I use Timer in tab bar controller??
    even if I switch to tabs the timer must remain running.
    Please Help me … Thanks.

Leave a Reply

Your email address will not be published. Required fields are marked *

close
Generic selectors
Exact matches only
Search in title
Search in content
Search in posts
Search in pages