SwiftUI聊天应用点击发送按钮清空自定义UITextView的方案
解决SwiftUI中自定义UITextView绑定文本清空不同步的问题
看起来你遇到的问题是:绑定的text变量清空后,自定义MessageField里的UITextView内容没跟着更新对吧?这是因为你的UIViewRepresentable实现里,updateUIView方法只处理了高度更新,没有根据绑定的text值同步更新UITextView的文本内容。我来帮你一步步修复这个问题:
问题根源
当你点击发送按钮设置self.text = ""时,SwiftUI会更新绑定变量,但MessageField的updateUIView方法并没有把这个空值同步到UITextView上,导致旧文本残留。另外当前实现也没在updateUIView中处理文本为空时显示占位符的逻辑。
修复步骤
1. 完善MessageField的updateUIView方法
修改该方法,让它根据绑定的text值同步更新UITextView内容,同时处理占位符显示,还要避免循环更新:
func updateUIView(_ uiView: UITextView, context: Context) { DispatchQueue.main.async { self.height = uiView.contentSize.height // 仅在文本不一致时更新,避免循环触发 if uiView.text != self.text { if self.text.isEmpty { uiView.text = placeholder uiView.textColor = .lightGray } else { uiView.text = self.text uiView.textColor = .label } } } }
2. 调整Coordinator的textViewDidChange方法
为了避免updateUIView和textViewDidChange之间的循环更新,添加文本一致性判断,同时处理占位符对应的空值逻辑:
func textViewDidChange(_ textView: UITextView) { DispatchQueue.main.async { self.parent.height = textView.contentSize.height // 处理占位符转空值,且仅在文本不同时更新绑定变量 let newText = textView.text == placeholder ? "" : textView.text if newText != self.parent.text { self.parent.text = newText } } }
3. 修正ChatRoom的小错误
你在调用ChatField时,height参数传的是普通变量height,但应该传绑定的$height,否则高度无法正确更新:
ChatField(text: $text, height: $height) { print("Sending following text:") print(self.text) }
4. 修正拼写错误
你的代码里Coordinator类名拼写错误(写成了Coordiator),这个会导致编译报错,我在下面的完整代码里已经修正。
完整修改后的MessageField.swift
import SwiftUI struct MessageField: UIViewRepresentable { @Binding var text: String @Binding var height: CGFloat var placeholder = "Message" func makeCoordinator() -> Coordinator { return Coordinator(parent: self, placeholder: placeholder) } func makeUIView(context: Context) -> UITextView { let view = UITextView() view.isEditable = true view.isScrollEnabled = true view.text = placeholder view.font = .systemFont(ofSize: 18) view.textColor = .lightGray view.backgroundColor = .clear view.delegate = context.coordinator return view } func updateUIView(_ uiView: UITextView, context: Context) { DispatchQueue.main.async { self.height = uiView.contentSize.height // 同步文本内容,避免循环更新 if uiView.text != self.text { if self.text.isEmpty { uiView.text = placeholder uiView.textColor = .lightGray } else { uiView.text = self.text uiView.textColor = .label } } } } class Coordinator: NSObject, UITextViewDelegate { var parent: MessageField var placeholder: String init(parent: MessageField, placeholder: String) { self.parent = parent self.placeholder = placeholder } func textViewDidBeginEditing(_ textView: UITextView) { if self.parent.text == "" { textView.text = "" textView.textColor = .label } } func textViewDidEndEditing(_ textView: UITextView) { if self.parent.text == "" { textView.text = placeholder textView.textColor = .lightGray } } func textViewDidChange(_ textView: UITextView) { DispatchQueue.main.async { self.parent.height = textView.contentSize.height // 处理占位符转空值,避免循环更新 let newText = textView.text == placeholder ? "" : textView.text if newText != self.parent.text { self.parent.text = newText } } } } }
这样修改后,点击发送按钮清空text变量时,updateUIView会触发,自动把UITextView内容设置回占位符,绑定变量也会保持为空,同时高度绑定也能正常工作了。
内容的提问来源于stack exchange,提问作者NikzJon
相关产品推荐
相关产品推荐

