In this blog, I will be implementing TimerApp with Combine
.
ContentView
import SwiftUI
import Combine
struct ContentView: View {
@State private var timerDuration: TimeInterval = 60
@State private var timerActive = false
@State private var timeRemaining: TimeInterval = 60
@State private var timerCancellable: AnyCancellable? // subscriber
// publish event in every second as a publisher
let timer = Timer.publish(every: 1, on: .main, in: .common)
var body: some View {
VStack {
Text("Timer \(timeString(time:timeRemaining))")
.font(.title2)
if(timerActive) {
Button("Stop Timer") {
self.timerActive = false
self.timerCancellable?.cancel()
}
} else {
Button("Start Timer") {
self.timerCancellable?.cancel() // cancel any existing timer before start the timer
self.timeRemaining = self.timerDuration
self.timerActive = true
// subscribe to publisher, timer
self.timerCancellable = timer.autoconnect().sink { _ in
// whenver event is triggered (every second), this callback is called
self.updateTimer()
}
}
}
// giver users options (1, 5, 10 minutes) using Picker View
Picker("Duration", selection: $timerDuration) {
Text("1 Minute").tag(TimeInterval(60))
Text("5 Minute").tag(TimeInterval(300))
Text("10 Minute").tag(TimeInterval(600))
}
}
.onDisappear {
self.timerCancellable?.cancel()
}
}
private func timeString(time: TimeInterval) -> String {
let intTime = Int(time)
let minutes = intTime / 60
let seconds = intTime % 60
return String(format: "%02i:%02i", minutes, seconds)
}
private func updateTimer() {
if(timerActive && timeRemaining > 0) {
timeRemaining -= 1
} else {
timerActive = false
}
}
}
Demo
Top comments (0)