DEV Community

Avelyn Hyunjeong Choi
Avelyn Hyunjeong Choi

Posted on

TimerApp with watchOS in Swift

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
        }
    }
}
Enter fullscreen mode Exit fullscreen mode

Demo

Image description

Top comments (0)