在 SwiftUI 中处理 UITextView 的 UIResponder
Handling UIResponder for UITextView in SwiftUI
我正在尝试在 SwiftUI 中为 UITextView
的现有子 class 处理 UIResponder
。我已经能够使用协调器模式来处理 UITextViewDelegate
但我在处理 UIResponder
.
时遇到了问题
在过去(使用 UIKit),我会做的是使用 NotificationCenter
在 UIViewController
的子 class 中为 UIResponder.keyboardWillShowNotification
添加一个观察者。
在 SwiftUI 中,我不确定将它放在哪里。我做了一件简单的事情,就是在 makeUIView
中重新使用 Coordinator class,如:
let nc = NotificationCenter.default
nc.addObserver(context.coordinator, selector: #selector(Coordinator.keyboardWillShow(notification:)), name: UIResponder.keyboardWillShowNotification, object: editorTextView)
但是 keyboardWillShow
方法永远不会被调用。我做错了吗?
我建议使用 Combine Publisher,这样您就不需要弄乱选择器,但这两种方式都应该有效。 observer/selector 模式在这个例子中被注释掉了,但是如果你取消注释它,观察者和发布者都应该在键盘出现时做出响应。
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
}
}
}
我正在尝试在 SwiftUI 中为 UITextView
的现有子 class 处理 UIResponder
。我已经能够使用协调器模式来处理 UITextViewDelegate
但我在处理 UIResponder
.
在过去(使用 UIKit),我会做的是使用 NotificationCenter
在 UIViewController
的子 class 中为 UIResponder.keyboardWillShowNotification
添加一个观察者。
在 SwiftUI 中,我不确定将它放在哪里。我做了一件简单的事情,就是在 makeUIView
中重新使用 Coordinator class,如:
let nc = NotificationCenter.default
nc.addObserver(context.coordinator, selector: #selector(Coordinator.keyboardWillShow(notification:)), name: UIResponder.keyboardWillShowNotification, object: editorTextView)
但是 keyboardWillShow
方法永远不会被调用。我做错了吗?
我建议使用 Combine Publisher,这样您就不需要弄乱选择器,但这两种方式都应该有效。 observer/selector 模式在这个例子中被注释掉了,但是如果你取消注释它,观察者和发布者都应该在键盘出现时做出响应。
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
}
}
}