I need to use UITextField in SwiftUI and I can publish text changes in UITextField to my view model with Binding variable.
But I cannot do the opposite. I want to be able to update the UITextField when the variables I publish in the ViewModel change. Because sometimes I want to be able to auto-fill TextFields with the data I pull from the internet.
struct Test: View {
@StateObject private var vm = TestVM()
var body: some View {
UIKitField(text: $vm.text)
.onAppear {
vm.fetchData()
}
}
}
class TestVM: ObservableObject {
@Published var text = ""
func fetchData() {
text = "abc" // here I want textfield's text to be updated.
}
}
struct UIKitField: UIViewRepresentable {
@Binding var text: String
private let textField = UITextField()
func makeUIView(context: Context) -> UITextField {
return textField
}
func updateUIView(_ uiView: UITextField, context: Context) {}
func makeCoordinator() -> Coordinator {
Coordinator(self)
}
final class Coordinator: NSObject {
private let parent: UIKitField
init(_ parent: UIKitField) {
self.parent = parent
super.init()
self.parent.textField.addTarget(self, action: #selector(editingChanged), for: .editingChanged)
}
@objc func editingChanged() {
parent.text = parent.textField.text!
}
}
}
CodePudding user response:
Update textField's
text
in updateUIView(_:context:)
.
From Apple Document:
When the state of your app changes, SwiftUI updates the portions of your interface affected by those changes. SwiftUI calls this method for any changes affecting the corresponding UIKit view.
func updateUIView(_ uiView: UITextField, context: Context) {
guard uiView.text != text else { return } //Change only if it doesn't match
uiView.text = text
}