You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.11 08:07:00