NEW: Start my new Ultimate Portfolio App course with a free Hacking with Swift+ trial! >>

How do I create a stopwatch with lap times in swiftUI?

Forums > SwiftUI

Does anyone know how to track laps in a stopwatch with SwiftUI? I already have this code:

class StopWatch: ObservableObject {

    @Published var timeElapsedFormatted = "00:00.00"
    @Published var mode: stopWatchMode = .stopped

    var secondsElapsed = 0.0
    var completedSecondsElapsed = 0.0
    var timer = Timer()

    func start() {
        self.mode = .timing
        timer = Timer.scheduledTimer(withTimeInterval: 0.01, repeats: true) { timer in
        self.secondsElapsed += 0.01

    func stop() {
        self.mode = .stopped
        self.completedSecondsElapsed = self.secondsElapsed
        self.secondsElapsed = 0.0
        self.timeElapsedFormatted = "00:00.00"

    func pause() {
        self.mode = .paused

    func formatTime() {
        let minutes: Int32 = Int32(self.secondsElapsed/60)
        let minutesString = (minutes < 10) ? "0(minutes)" : "(minutes)"
        let seconds: Int32 = Int32(self.secondsElapsed) - (minutes * 60)
        let secondsString = (seconds < 10) ? "0(seconds)" : "(seconds)"
        let milliseconds: Int32 = Int32(self.secondsElapsed.truncatingRemainder(dividingBy: 1) * 100)
        let millisecondsString = (milliseconds < 10) ? "0(milliseconds)" : "(milliseconds)"
        self.timeElapsedFormatted = minutesString + ":" + secondsString + "." + millisecondsString

enum stopWatchMode {
    case timing
    case stopped
    case paused

But I have a start, pause, stop and laps button. When I click the laps button, the lap time should be saved in a list below the stopwatch. Does anyone know how to solve this?


Without coding it up, I'd think you would use a Date object for your start time, and it would also assign it as the lapStartTime.

When you want a lap split time, create a second Date object as the lapEndTime, do some date math w/ CalendarComponents and output the difference in whatever increment you are looking to use. Also, at this point the lapStartTime would be updated to use the lapEndTime as the end of one split is the start of the next.

On a side note, do you really need to loop your timer so tightly (1/100th of a second)? That would seem to use a lot of cycles, when you could have it update maybe on the 1/10th of a second for showing the running display. When you actually select to stop, you would use that instant in time to create an endTimingDate and do similar date math as used for the lap split timer.

Does this makes sense?


Hacking with Swift is sponsored by Instabug

SPONSORED Catch bugs as soon as they happen and know exactly why a crash occurred. Instabug's SDK grabs all the logs they need to fix bugs, crashes and performance issues in minutes instead of days. Get screenshots, device details, network logs, repro steps, and tons of other critical insights needed to resolve issues and prioritize product backlogs straight from your dashboard. It only takes a minute to integrate!

Get started now

Sponsor Hacking with Swift and reach the world's largest Swift community!

Reply to this topic…

You need to create an account or log in to reply.

All interactions here are governed by our code of conduct.

Unknown user

You are not logged in

Log in or create account

Link copied to your pasteboard.