Swift 3: Programming a simple stopwatch

Swift 3: Programming a simple stopwatch

Published March 3, 2017 by 3 Comments

For the last while, I have been extending my programming skill set by learning Swift. Swift is a programming language for MacOS, iOS, watchOS and tvOS applications. As both a resource for myself and hopefully a resource for fellow programmers, I thought I might start publishing some of my early scratchings. I emphasise early! Don’t expect the entire source code to an Uber app… yet.

The following code creates a simple stopwatch/timer. It could be easily extended to include advanced functionality like reverse timers, alarms, notifications, etc. I learnt a lot from this so I hope it may be useful to your Swift journey. I would love any feedback so feel free to comment.

Amazon Recommends

I used the following very helpful sources when researching how I should approach this Swift snippet:

I separated the three time blocks (min/sec/ms) into separate labels as I found that putting them all into one label made for a shaky viewing experience. I suspect by having them separate will allow for easy design enhancements.

//
//  ViewController.swift
//  Simple Stopwatch
//
//  Created by Mike Little on 2/03/17.
//  Copyright © 2017 Creative Digital. All rights reserved.
//

import UIKit

class ViewController: UIViewController {

    weak var timer: Timer?
    var startTime: Double = 0
    var time: Double = 0
    var elapsed: Double = 0
    var status: Bool = false
    
    @IBOutlet weak var labelMinute: UILabel!
    @IBOutlet weak var labelSecond: UILabel!
    @IBOutlet weak var labelMillisecond: UILabel!
    @IBOutlet weak var resetBtn: UIButton!
    
    override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view, typically from a nib.
        
        // No point enabling reset until stopwatch actually started
        resetBtn.isEnabled = false
        
    }

    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
        // Dispose of any resources that can be recreated.
    }

    @IBAction func toggleStartStop(_ sender: UIButton!) {
        
        // If button status is true use stop function, relabel button and enable reset button
        if (status) {
            stop()
            sender.setTitle("START", for: .normal)
            resetBtn.isEnabled = true
        
        // If button status is false use start function, relabel button and disable reset button
        } else {
            start()
            sender.setTitle("STOP", for: .normal)
            resetBtn.isEnabled = false
        }
        
    }
    
    @IBAction func resetBtn(_ sender: Any) {
        
        // Invalidate timer
        timer?.invalidate()
        
        // Reset timer variables
        startTime = 0
        time = 0
        elapsed = 0
        status = false
        
        // Reset all three labels to 00
        let strReset = String("00")
        labelMinute.text = strReset
        labelSecond.text = strReset
        labelMillisecond.text = strReset
        
    }
    
    func start() {
        
        startTime = Date().timeIntervalSinceReferenceDate - elapsed
        timer = Timer.scheduledTimer(timeInterval: 0.01, target: self, selector: #selector(updateCounter), userInfo: nil, repeats: true)
        
        // Set Start/Stop button to true
        status = true
        
    }

    func stop() {
        
        elapsed = Date().timeIntervalSinceReferenceDate - startTime
        timer?.invalidate()
        
        // Set Start/Stop button to false
        status = false
        
    }
    
    func updateCounter() {
        
        // Calculate total time since timer started in seconds
        time = Date().timeIntervalSinceReferenceDate - startTime
        
        // Calculate minutes
        let minutes = UInt8(time / 60.0)
        time -= (TimeInterval(minutes) * 60)
        
        // Calculate seconds
        let seconds = UInt8(time)
        time -= TimeInterval(seconds)
        
        // Calculate milliseconds
        let milliseconds = UInt8(time * 100)
        
        // Format time vars with leading zero
        let strMinutes = String(format: "%02d", minutes)
        let strSeconds = String(format: "%02d", seconds)
        let strMilliseconds = String(format: "%02d", milliseconds)
        
        // Add time vars to relevant labels
        labelMinute.text = strMinutes
        labelSecond.text = strSeconds
        labelMillisecond.text = strMilliseconds
        
    }
}
Amazon Recommends

Tags: , , ,

Comments

  • John kirk says:

    hi,
    if I setup the timer for 10 seconds, then I need to start another timer for 5 seconds after the first timer stopped before the first timer running back?
    I stopped the first one after 10 seconds, but the second timer started but stop counting!

    appreciated your help,
    Thanks,
    John

  • Max Schellenberg says:

    Hey there, thanks this helped. How would I count down from 30 seconds?

Leave a Reply

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