swiftui - 在 UITextField 与 UIViewRepresentable 和 SwifUI 之间绑定文本时出现问题
问题描述
我正在尝试在 SwiftUI 中制作一个“表情符号选择器”,它会调出表情符号键盘,允许用户选择一个表情符号,然后关闭键盘。我正在使用带有字符串绑定的 UIViewRepresntable 中包装的 UITextField,但是由于某种原因,字符串的值永远不会更新。
这是我到目前为止的代码:
/// Allows a user to pick an emoji character using the Emoji keyboard.
/// - Note: This does not prevent the user from manually switching to other keyboards and inputting a non-Emoji character
struct EmojiPicker: UIViewRepresentable {
@Binding var emoji: String
func makeUIView(context: UIViewRepresentableContext<EmojiPicker>) -> EmojiUITextField {
let textField = EmojiUITextField(frame: .zero)
textField.text = emoji
textField.delegate = context.coordinator
textField.autocorrectionType = .no
textField.returnKeyType = .done
textField.textAlignment = .center
textField.tintColor = .clear
return textField
}
func updateUIView(_ uiView: EmojiUITextField, context: Context) {
self.emoji = uiView.text!
}
func makeCoordinator() -> EmojiTextFieldCoordinator {
return EmojiTextFieldCoordinator(self)
}
}
internal class EmojiTextFieldCoordinator: NSObject, UITextFieldDelegate {
var emojiTextField: EmojiPicker
init(_ textField: EmojiPicker) {
self.emojiTextField = textField
}
func textFieldDidEndEditing(_ textField: UITextField) {
self.emojiTextField.emoji = textField.text!
}
func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool {
textField.text = string
if let text = textField.text, text.count == 1 {
self.emojiTextField.emoji = textField.text!
UIApplication.shared.sendAction(#selector(UIResponder.resignFirstResponder), to: nil, from: nil, for: nil)
}
return true
}
}
internal class EmojiUITextField: UITextField {
override var textInputContextIdentifier: String? {
return ""
}
override var textInputMode: UITextInputMode? {
return UITextInputMode.activeInputModes.first {
$0.primaryLanguage == "emoji"
}
}
override func selectionRects(for range: UITextRange) -> [UITextSelectionRect] {
return []
}
}
解决方案
这是修复,唯一修改的部分,(使用 Xcode 12 / iOS 14 测试)
func updateUIView(_ uiView: EmojiUITextField, context: Context) {
if self.emoji != uiView.text! { // << update only on change, otherwise
self.emoji = uiView.text! // it result in cycle and dropped
}
}
这是用于测试的视图
struct ContentView: View {
@State private var text = "<none>"
var body: some View {
VStack {
Text("Get: \(text)")
EmojiPicker(emoji: $text)
}
}
}
推荐阅读
- java - 是否应该在 Java 中扩展 ArrayList
- angular - 为重复组件的每个实例生成确定性 ID
- angularjs - $request->input 总是返回 null
- saml - 构建 SP 元数据时出错:IDP_CERT_OR_FINGERPRINT_NOT_FOUND_AND_REQUIRED
- php - 在 PHP 中解析来自 SEMRush API 的数据 [分号分隔]
- scheme - 违反球拍合约(最大递归函数)
- swift - NSClickGestureRecognizer - 识别后如何传递点击
- jenkins - 如何在安装在远程 PC 上的 Jenkins 中定义 POM 位置
- r - 创建可以判断变量输入是字符串还是符号的 dplyr 函数
- c - C:将二维数组交给双指针