UITextField不更新以更改ObservableObject(SwiftUI)

时间:2020-08-04 11:35:04

标签: swiftui combine observableobject

我正在尝试制作一个UITextView来编辑值currentDisplayedAddress。该值也会被其他视图更改,我希望UITextView在发生这种情况时更新其文本。

视图正确初始化,我可以毫无问题地编辑currentDisplayedAddress中的AddressTextField并触发相关的视图更新。但是,当值被其他视图更改时,即使textField.textupdateUIView内打印正确的更新值并且其他视图也相应地更新,textField的文本也不会更改。

我不知道是什么原因造成的。任何帮助都非常感谢。

struct AddressTextField: UIViewRepresentable {
    private let textField = UITextField(frame: .zero)
    var commit: () -> Void
    @EnvironmentObject var userData: UserDataModel

    func makeUIView(context: UIViewRepresentableContext<AddressTextField>) -> UITextField {
        textField.text = self.userData.currentDisplayedAddress
        textField.delegate = context.coordinator
        return textField
    }

    func updateUIView(_ uiView: UITextField, context: UIViewRepresentableContext<AddressTextField>) {
        if self.textField.text != self.userData.currentDisplayedAddress {
        DispatchQueue.main.async {
            self.textField.text = self.userData.currentDisplayedAddress
            }
        }
    }

   (...)

    func makeCoordinator() -> Coordinator { Coordinator(self) }

    class Coordinator: NSObject, UITextFieldDelegate {
        var addressTextField: AddressTextField

        func textFieldShouldReturn(_ textField: UITextField) -> Bool {   //delegate method
            textField.resignFirstResponder()
            addressTextField.userData.currentDisplayedAddress = textField.text ?? String()
            addressTextField.commit()
            return true
        }
    }
}

1 个答案:

答案 0 :(得分:0)

您不应将UITextField创建为属性,因为可以在父更新期间重新创建AddressTextField结构。 makeUIView正是创建UI实例的地方,可表示对象正在代表您处理其引用。

因此,这里是固定的变体。使用Xcode 11.4 / iOS 13.4进行了测试

struct AddressTextField: UIViewRepresentable {
    var commit: () -> Void = {}
    @EnvironmentObject var userData: UserDataModel

    func makeUIView(context: UIViewRepresentableContext<AddressTextField>) -> UITextField {
        let textField = UITextField(frame: .zero)
        textField.text = self.userData.currentDisplayedAddress
        textField.delegate = context.coordinator
        return textField
    }

    func updateUIView(_ textField: UITextField, context: UIViewRepresentableContext<AddressTextField>) {
        if textField.text != self.userData.currentDisplayedAddress {
            textField.text = self.userData.currentDisplayedAddress
        }
    }

    func makeCoordinator() -> Coordinator { Coordinator(self) }

    class Coordinator: NSObject, UITextFieldDelegate {
        var addressTextField: AddressTextField
        init(_ addressTextField: AddressTextField) {
            self.addressTextField = addressTextField
        }
        func textFieldShouldReturn(_ textField: UITextField) -> Bool {   //delegate method
            textField.resignFirstResponder()
            addressTextField.userData.currentDisplayedAddress = textField.text ?? String()
            addressTextField.commit()
            return true
        }
    }
}