Обработка UIResponder для UITextView в SwiftUI - PullRequest
1 голос
/ 14 апреля 2020

Я пытаюсь обработать UIResponder для существующего подкласса UITextView в SwiftUI. Я смог использовать шаблон Coordinator для обработки UITextViewDelegate, но у меня возникли проблемы с UIResponder.

В прошлом (с UIKit) я бы использовал NotificationCenter для добавить наблюдателя для UIResponder.keyboardWillShowNotification в подкласс UIViewController.

В SwiftUI я не уверен, где его поставить. Я сделал простую вещь, которая заключается в повторном использовании класса Coordinator в makeUIView, например:

    let nc = NotificationCenter.default
    nc.addObserver(context.coordinator, selector: #selector(Coordinator.keyboardWillShow(notification:)), name: UIResponder.keyboardWillShowNotification, object: editorTextView)

Но метод keyboardWillShow никогда не вызывается. Я делаю это неправильно?

1 Ответ

2 голосов
/ 14 апреля 2020

Я бы порекомендовал использовать Combine Publisher, чтобы вам не приходилось связываться с селекторами, но это должно работать в любом случае. Шаблон наблюдателя / селектора закомментирован в этом примере, но если вы раскомментируете его, наблюдатель и издатель должны ответить, когда появится клавиатура.

    import Combine
    import SwiftUI
    import UIKit

    struct MyTextView: UIViewRepresentable {
    // Pass in the binding to the string from the SwiftUI view
    var text: Binding<String>

    init(text: Binding<String>) {
        self.text = text
    }

    func makeUIView(context: Context) -> UITextField {
        let tf = UITextField()
        tf.delegate = context.coordinator
        tf.text = context.coordinator.text.wrappedValue // Access the wrapped value in the binding
        return tf
    }

    func updateUIView(_ uiView: UITextField, context: Context) {
        //
    }

    func makeCoordinator() -> MyTextViewDelegate {
        let delegate = MyTextViewDelegate(text: text)
        return delegate
    }

    class MyTextViewDelegate: NSObject, UITextFieldDelegate {
//      let nc = NotificationCenter.default
        var text: Binding<String>

        // You can use a Combine Publisher rather than dealing with selectors
        var subscriber: AnyCancellable?

        init(text: Binding<String>) {
            self.text = text
            super.init()
            subscriber = NotificationCenter.default.publisher(for: UIResponder.keyboardWillShowNotification)
                .sink() { [weak self] note in
                    print(self?.text.wrappedValue ?? "nil")
                    print("Publisher called -> " + note.description)
            }
//            nc.addObserver(self, selector: #selector(keyboardWillShow(notification:)), name: UIResponder.keyboardWillShowNotification, object: nil)
        }


//        @objc func keyboardWillShow(notification: Notification) {
//            print("Selector called -> " + notification.description)
//        }

        // Value should update in SwiftUI when return key is pressed to show that the data flows
        func textFieldShouldReturn(_ textField: UITextField) -> Bool {
            self.text.wrappedValue = textField.text ?? ""
            print(textField.text!)
            return true
        }
    }
}
...