简体   繁体   English

为什么自定义绑定不更新 SwiftUI TextField?

[英]Why does custom Binding not update SwiftUI TextField?

I feel like I'm misunderstanding how Binding works in SwiftUI, in that I do not understand why the first TextField below does not update when the text view model property changes:我觉得我误解了 SwiftUI 中Binding工作原理,因为我不明白为什么当text视图模型属性更改时下面的第一个TextField不会更新:

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()
    }
}

Typing in the first TextField always updates second one (and the Text label), but typing in the second TextField only propagates changes to the Text label, shown here:在第一个TextField键入总是更新第二个(和Text标签),但在第二个TextField键入只会将更改传播到Text标签,如下所示:

模拟器截图

In my actual use case, the list of TextField views is dynamically generated from a user-defined template, likewise with custom bindings to a @Published complex object (ie not as simple as a String ) on MyViewModel .在我的实际使用的情况下,列表中TextField被动态地从一个用户定义的模板生成的视图,同样与自定义绑定至@Published复杂对象(即,不作为简单如String )上MyViewModel In my limited experience, I believe the dynamic nature of the view prevents me from coding it in a straight-forward fashion, as seen with the second TextField .以我有限的经验,我相信视图的动态特性阻止我以直接的方式对其进行编码,如第二个TextField所见。

My guess is that SwiftUI has no insight that the custom binding should even need to be refreshed, in which case my question becomes: How can I tell the binding to "refresh" the TextField while also supporting dynamically-generated content?我的猜测是 SwiftUI 不知道自定义绑定甚至应该需要刷新,在这种情况下,我的问题变成:如何让绑定“刷新” TextField同时还支持动态生成的内容?

First, consider this line code首先,考虑这一行代码

binding = Binding(get: { self.text }, set: { self.text = $0 })

You are assigning binding value to self.text by self.text = $0 , it means now self.text value updated and your view is rendering with new value so, it will display with new value in the all place.您正在通过self.text = $0self.text分配绑定值,这意味着现在self.text值已更新并且您的视图正在使用新值呈现,因此它将在所有位置以新值显示。

Now, you are changing the value of @Published var by the second field.现在,您正在通过第二个字段更改@Published var 的值。 when you are changing this var, your just changing the value of @Published var text: String this var and it's not related to this binding var var binding: Binding<String>!当您更改此 var 时,您只需更改@Published var text: String this var 的值,它与此绑定 var var binding: Binding<String>!无关var binding: Binding<String>! there is no communication or connection.没有通信或连接。 so var binding: Binding<String>!所以var binding: Binding<String>! value is not changed and remains the same as the old value.值未更改并保持与旧值相同。

If you want to update both directions, you also need to add this code如果要更新两个方向,还需要添加这个代码

@Published var text: String = "Hello" {
        didSet {
            binding = Binding(get: { self.text }, set: { self.text = $0 }) // <-- Here
        }
    }

So now it will reflect on both sides.所以现在它会反映在双方。


If you have still confusion Replace this line如果您仍有困惑 更换此行

var binding: Binding<String>!

with this有了这个

@Published var binding: String = ""

And now think.现在想想。 The above way is the same way as your code, just have a different declaration.上述方式与您的代码方式相同,只是有不同的声明。 These are now two different var but doing the same things.这些现在是两个不同的 var 但做同样的事情。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM