0

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?

PeeWee
  • 11

1 Answers1

0

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
                }
            }
    }
}
sergio_veliz
  • 149
  • 9
  • you need to put the timer in @State otherwise it'll restart every time the ContentView is init and if that happens faster than once per second the timer will fire more often than you want. – malhal Apr 27 '22 at 11:05