Skip to content

Instantly share code, notes, and snippets.

@benigumocom
Last active March 18, 2024 08:29
Show Gist options
  • Save benigumocom/36121d8c46a27636406e1e455c05ebb6 to your computer and use it in GitHub Desktop.
Save benigumocom/36121d8c46a27636406e1e455c05ebb6 to your computer and use it in GitHub Desktop.
【SwiftUI】Stop watch sample 👉 https://android.benigumo.com/20240225/stop-watch/
import SwiftUI
@Observable final class ScheduledTimer {
var elapsed = TimeInterval.zero
private var timer: Timer?
func start() {
timer = Timer.scheduledTimer(withTimeInterval: 0.001, repeats: true) { _ in
self.elapsed += 0.001
}
}
func reset() {
elapsed = .zero
}
func stop() {
timer?.invalidate()
}
}
@Observable final class TaskedTimer {
var elapsed = TimeInterval.zero
private var task: Task<(), Never>?
func start() {
if task?.isCancelled ?? true { // keep task single
task = Task {
let start = Date().addingTimeInterval(-elapsed)
do {
while true {
try await Task.sleep(for: .milliseconds(1))
elapsed = Date().timeIntervalSince(start)
}
} catch {
if Task.isCancelled {
print("cancelled.")
}
}
}
}
}
func reset() {
elapsed = .zero
}
func stop() {
task?.cancel()
}
}
struct StopWatch: View {
private var st = ScheduledTimer()
private var tt = TaskedTimer()
@State private var running = false
var body: some View {
VStack {
Text(String(format: "st : %.3f", st.elapsed))
Text(String(format: "tt : %.3f", tt.elapsed))
HStack {
Button(running ? "stop" : "start") {
if running {
st.stop()
tt.stop()
} else {
st.start()
tt.start()
}
running.toggle()
}
Button("reset") {
st.reset()
tt.reset()
}
.disabled(running || st.elapsed == .zero || tt.elapsed == .zero)
}
.buttonStyle(.borderedProminent)
}
.monospaced()
}
}
#Preview {
StopWatch()
.frame(width: 300, height: 300)
}
@benigumocom
Copy link
Author

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment