'Problems with timer and views in SwiftUI

I try to develop an WatchOS app, where the views are feeded by a timer:

import SwiftUI
import Combine

class AcidityTimer: ObservableObject {
    @Published var num: Int = 0
    private var subscription: AnyCancellable?
    
    
    init() {
        Timer.scheduledTimer(withTimeInterval: 1.0, repeats: true) { _ in
            self.num += 1
            if self.num == 101 {
                self.num = 0
            }
        }
    }
}

struct AcidityTextView: View {
    @EnvironmentObject var acTimer: AcidityTimer
    @State var acidity: Double = 0.0
    
    var body: some View {
        Text(String(format: "Acidity: %.1f", acidity))
            .onReceive(acTimer.$num) { result in
                acidity = Double(result) / 10.0
            }
    }
}

struct AcidityGaugeView: View {
    @State var acidity = 0.0
    @EnvironmentObject var acTimer: AcidityTimer
    
    var body: some View {
        Gauge(value: acidity, in: 0...10) {
            Image(systemName: "drop.fill")
                .foregroundColor(.green)
        } currentValueLabel: {
            Text("\(acidity, specifier: "%.1f")")
        } minimumValueLabel: {
            Text("0")
        } maximumValueLabel: {
            Text("10")
        }
        .gaugeStyle(CircularGaugeStyle())
        .onReceive(acTimer.$num) { result in
            acidity = Double(result) / 10.0
        }
    }
}

struct ContentView: View {
    @ObservedObject var acTimer = AcidityTimer()
    @State var counter: Int = 0
    
    var body: some View {
        TabView {
            AcidityTextView()
                .environmentObject(acTimer)
            AcidityGaugeView()
                .environmentObject(acTimer)
        }
    }
}

struct ContentView_Previews: PreviewProvider {
    static var previews: some View {
        ContentView()
    }
}

The app itself runs fine on the Apple Watch simulator, but I get the error message:

[SwiftUI] Accessing State's value outside of being installed on a View. This will result in a constant Binding of the initial value and will not update.

Any idea what's wrong?



Solution 1:[1]

You use timer on initial and nowhere didn't stopped or update You can change implementation to

struct ContentView: View {
    @State var timeRemaining = 10
    let timer = Timer.publish(every: 1, on: .main, in: .common).autoconnect()

    var body: some View {
        Text("\(timeRemaining)")
            .onReceive(timer) { _ in
                if timeRemaining > 0 {
                    timeRemaining -= 1
                }
            }
    }
}

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 sergio_veliz