swiftswiftuicombinexcode12

Accessing ViewModel field in SwiftUI using Xcode 12: "Accessing State's value outside of being installed on a View"


I think this error message is new to SwiftUI in Xcode 12 since it gave 0 hits in Google while the message itself is fairly generic:

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.

I have the following code (removed some fluff):

public struct ContentView: View {
    @ObservedObject var model: RootViewModel

    public var body: some View {
        VStack(alignment: .center, content: {
            Picker(selection: model.$amount, label: Text("Amount")) {
                Text("€1").tag(1)
                Text("€2").tag(2)
                Text("€5").tag(5)
                Text("€10").tag(10)
            }.pickerStyle(SegmentedPickerStyle())
            Text("Donating: €\(model.amount)").font(.largeTitle)
        }).padding(.all, 20.0)
    }
}

public class RootViewModel: ObservableObject {
    @State public var amount: Int = 1
}

I used to have the field right in the ContentView and that worked alright. Now the UI does not update anymore and I got that run-time warning instead.


Solution

  • Thanks to @Andrew's answer I figured out how to make it work again. First you change the @State to @Published:

    @Published public var amount: Int = 1
    

    Next, you need to change how your Picker is bound to the data:

    Picker(selection: $model.amount, label: Text("Amount")) {
        Text("€1").tag(1)
        Text("€2").tag(2)
        Text("€5").tag(5)
        Text("€10").tag(10)
    }.pickerStyle(SegmentedPickerStyle())
    

    So we went from model.$amount to $model.amount.