我觉得我误解了 Binding
在 SwiftUI 中的工作方式,因为我不明白为什么当 {{1 }} 查看模型属性更改:
TextField
输入第一个 text
总是更新第二个(和 class MyViewModel: ObservableObject {
@Published var text: String = "Hello"
var binding: Binding<String>!
init() {
binding = Binding(get: { self.text }, set: { self.text = $0 })
}
}
struct MyView: View {
@StateObject var viewModel = MyViewModel()
var body: some View {
VStack {
Text("Actual: " + viewModel.text)
TextField("Field 1", text: viewModel.binding)
TextField("Field 2", text: $viewModel.text)
}
}
}
struct MyView_Previews: PreviewProvider {
static var previews: some View {
MyView()
}
}
标签),但输入第二个 TextField
只会将更改传播到 Text
标签,如图所示这里:
在我的实际用例中,TextField
视图列表是从用户定义的模板动态生成的,同样具有到 Text
复杂对象的自定义绑定(即不像 {{ 1}}) 在 TextField
。以我有限的经验,我认为视图的动态特性使我无法以直接的方式对其进行编码,如第二个 @Published
所示。
我的猜测是 SwiftUI 不知道自定义绑定甚至应该需要刷新,在这种情况下,我的问题变成:如何告诉绑定“刷新”String
同时还支持动态-生成的内容?
答案 0 :(得分:0)
首先考虑这行代码
binding = Binding(get: { self.text }, set: { self.text = $0 })
您正在通过 self.text
将绑定值分配给 self.text = $0
,这意味着现在 self.text
值已更新,并且您的视图正在使用新值呈现,因此,它将以新值显示在所有地点。
现在,您正在通过第二个字段更改 @Published
var 的值。当您更改此 var 时,您只是更改了 @Published var text: String
此 var 的值,并且与此绑定 var var binding: Binding<String>!
无关,没有通信或连接。所以 var binding: Binding<String>!
值不会改变,并保持与旧值相同。
如果要更新两个方向,还需要加上这个代码
@Published var text: String = "Hello" {
didSet {
binding = Binding(get: { self.text }, set: { self.text = $0 }) // <-- Here
}
}
所以现在它会在两面都有反映。
如果你还有困惑 替换这一行
var binding: Binding<String>!
有了这个
@Published var binding: String = ""
现在想想。上述方式与您的代码方式相同,只是有不同的声明。它们现在是两个不同的 var,但做同样的事情。