App 21 — 24 Apps You Can Make Today
StopWatch
A working stopwatch with start, stop, and reset — Timer, elapsed time, and formatted display.
- ios
A stopwatch needs to count up on its own while displaying the time precisely. It also needs three buttons that work correctly regardless of the current state. This is a surprisingly rich little app.
What you'll build
A large elapsed time display and three buttons: Start, Stop, Reset. The display counts up while running, freezes when stopped, and resets to zero on demand.
Key concepts
Timer for steady updates — Fire a timer 100 times per second to track hundredths of a second.
@State var elapsed: TimeInterval = 0
@State var timer: Timer?
func start() {
timer = Timer.scheduledTimer(withTimeInterval: 0.01, repeats: true) { _ in
elapsed += 0.01
}
}
func stop() {
timer?.invalidate()
timer = nil
}
func reset() {
stop()
elapsed = 0
}
TimeInterval is Double — elapsed is just a Double representing seconds. Hundredths of a second are decimals.
Formatted display — Convert elapsed into MM:SS.hh format for display.
var display: String {
let minutes = Int(elapsed) / 60
let seconds = Int(elapsed) % 60
let hundredths = Int((elapsed * 100).truncatingRemainder(dividingBy: 100))
return String(format: "%02d:%02d.%02d", minutes, seconds, hundredths)
}
Button state — Disable Start when running, disable Stop when not running, so the interface always makes sense.
Button("Start") { start() }
.disabled(timer != nil)
Managing timer state
The timer variable being nil vs non-nil is itself state — it tells you whether the stopwatch is running. That's a cleaner signal than a separate isRunning: Bool because it's impossible for the timer to be running while timer == nil.
Download and run it
Open the Playgrounds file from GitHub, hit Run, and time something.