使用 Xcode 12 访问 SwiftUI 中的 ViewModel 字段:“访问安装在视图之外的状态值”

Dep*_*o B 10 swift swiftui combine xcode12

我认为此错误消息是 Xcode 12 中的 SwiftUI 的新消息,因为它在 Google 中的点击率为 0,而该消息本身相当通用:

在安装在 View 之外访问 State 的值。这将导致初始值的常量绑定并且不会更新。

我有以下代码(删除了一些绒毛):

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
}
Run Code Online (Sandbox Code Playgroud)

我曾经有field权利,ContentView而且工作正常。现在 UI 不再更新,而是我收到了运行时警告。

Dep*_*o B 18

感谢@Andrew 的回答,我想出了如何让它再次工作。首先,您将更@State改为@Published

    @Published public var amount: Int = 1
Run Code Online (Sandbox Code Playgroud)

接下来,您需要更改Picker绑定到数据的方式:

            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())
Run Code Online (Sandbox Code Playgroud)

所以我们从model.$amount$model.amount


Joe*_*ick 6

与其他答案类似, anApp与 a 不同View。您将收到相同的错误消息,但原因不如 OP 示例中那么明显。

@main
struct MyCoolApp: App {
    @SceneStorage("testSceneStorage") private var persisted = ""

    var body: some Scene {
        WindowGroup {
            Text(persisted) // "Accessing a SceneStorage value outside of being installed on a View. This will always return the default value."
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

对我来说,此错误消息中的“installed”一词令人困惑。我希望他们能采用类似“访问未在视图上定义的场景存储/状态值”之类的内容。