Skip to content

Timer State Observing

Alina P edited this page Dec 12, 2024 · 15 revisions

Gdyby wszyscy zajmowali się tylko swoimi własnymi sprawami, Ziemia obracałaby się z pewnością szybciej, niż się obraca.

Timer State Observing

Overview

The library offers various ways to monitor updates to the timer state. You can use closures, binding, or subscribe to publisher updates.

Important

The frequency for calling Completion block, updating Binding values and Publishers can be configured with function publish. See more here Timer Set-Up

Ways to observe changes

Available Properties

  • @Published var timerTime: MTime

    • Current time publisher
    • By default, updates are triggered each time the timer status is marked as finished.
  • @Published public var timerStatus: MTimerStatus

    • Status publisher
    • Available states: notStarted, inProgress, cancelled, paused, finished
    • Value updates:
  • @Published public private(set) var timerProgress

    • Progress publisher
    • By default, updates are triggered each time the timer status is marked as finished.

Available Methods

  • func onTimerStatusChange(_ action: @escaping (_ timerStatus: MTimerStatus) -> ()) -> MTimer

    • Publishes the timer status changes every.
  • func bindTimerStatus(timerStatus: Binding<MTimerStatus>) -> MTimer

    • Publishes the timer status changes every.
  • func onTimerProgressChange(_ action: @escaping (_ progress: Double) -> ()) -> MTimer

    • Publishes the timer progress changes.
  • func bindTimerProgress(progress: Binding<Double>) -> MTimer

    • Publishes the timer progress changes.

Code Examples

Observing state with Publishers

struct ExampleView: View {
    @ObservedObject var timer = MTimer(.id)
    
    var body: some View {
        VStack {
            Text("Status: \(timer.timerStatus)")
            Text("Progress: \(timer.timerProgress)")
            Text("Time: \(timer.timerTime.toString())"))
            Spacer()

            Button("Start", action: onActionButtonTap)
        }
        .padding()
    }
}

private extension ExampleView {
    func onActionButtonTap() {
        try? timer
            .publish(every: 1, tolerance: 0.8)
            .start(to: 16)
    }
}

Bind changes

struct ExampleView: View {
    @State var progress: Double = 0
    @State var status: MTimerStatus = .notStarted
    @State var time: MTime = .init()
    
    var body: some View {
        VStack {
            Text("Status: \(status)")
            Text("Progress: \(progress)")
            Text("Time: \(time.toString())")
            Spacer()

            Button("Start", action: onActionButtonTap)
        }
        .padding()
    }
}

private extension ExampleView {
    func onActionButtonTap() {
       try? MTimer(.id)
            .publish(every: 1, currentTime: $time)
            .bindTimerStatus(timerStatus: $status)
            .bindTimerProgress(progress: $progress)
            .start(to: 10)
    }
}

Observing state with Combine

import Combine

@MainActor class ViewModel {
    private var cancellable: Set<AnyCancellable> = []
    let timer = MTimer(.id)
    
    init() { observeTimer() }
}

private extension ViewModel {
    func observeTimer() {
        observeStatus()
        observeProgress()
        observeTime()
    }
}

private extension ViewModel {
    func observeStatus() {
        timer.$timerStatus
            .sink { print("Status: ", $0) }
            .store(in: &cancellable)
    }
    func observeProgress() {
        timer.$timerProgress
            .sink { print("Progress: ", $0) }
            .store(in: &cancellable)
    }
    func observeTime() {
        timer.$timerTime
            .sink { print("Time: ", $0.toString()) }
            .store(in: &cancellable)
    }
}

Observing state with Callbacks

struct ExampleView: View {
    @State var progress: Double = 0
    @State var status: MTimerStatus = .notStarted
    @State var time: MTime = .init()
    
    var body: some View {
        VStack {
            Text("Status: \(status)")
            Text("Progress: \(progress)")
            Text("Time: \(time.toString())")
            Spacer()

            Button("Start", action: onActionButtonTap)
        }
        .padding()
    }
}

private extension ExampleView {
    func onActionButtonTap() {
        try? MTimer(.id)
             .publish(every: 1) { time = $0 }
             .onTimerStatusChange { status = $0 }
             .onTimerProgressChange { progress = $0 }
             .start(to: 10)
    }
}

See also