UITextField не обновляется до изменения в ObservableObject (SwiftUI) - PullRequest
1 голос
/ 04 августа 2020

Я пытаюсь создать UITextView, который редактирует значение currentDisplayedAddress. Значение также изменяется другими представлениями, и я хочу, чтобы UITextView обновлял свой текст, когда это происходит.

Представление инициализируется правильно, и я могу редактировать currentDisplayedAddress из AddressTextField без проблем и запускать соответствующие просматривать обновления. Однако, когда значение изменяется другими представлениями, текст textField не изменяется, даже если textField.text печатает правильное обновленное значение внутри updateUIView и другие представления обновляются соответственно.

Я понятия не имею, что может вызвали это. Любая помощь очень ценится.

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 голосов
/ 04 августа 2020

Вы не должны создавать 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
        }
    }
}
...