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

SwiftUI中为UITextView添加清除按钮的实现问题

SwiftUI中清空UITextView文本的解决方案

问题根源

你的代码核心问题是TextInputView中的text属性使用了@State而非@Binding,导致父视图的content无法和UITextView的文本实现双向绑定,直接设置content = ""无法同步到底层的UITextView。

修复步骤及代码

1. 修正TextInputView的绑定关系

将text属性改为@Binding,补充desiredHeight和hasContent的绑定(原代码中父视图传递了这两个参数但子视图未定义),并优化更新逻辑避免循环刷新:

struct TextInputView: UIViewRepresentable {
    @Binding var text: String
    @Binding var desiredHeight: CGFloat
    @Binding var hasContent: Bool
    var foregroundColor: Color = .gray

    func makeUIView(context: Context) -> UITextView {
        let view = UITextView()
        view.font = .systemFont(ofSize: 16)
        view.textColor = UIColor(foregroundColor)
        view.isEditable = true
        view.isScrollEnabled = true
        view.delegate = context.coordinator
        return view
    }

    func updateUIView(_ uiView: UITextView, context: Context) {
        // 仅当文本不一致时更新,避免循环刷新
        if uiView.text != text {
            uiView.text = text
        }
        uiView.textColor = UIColor(foregroundColor)
        // 同步内容状态
        hasContent = !text.isEmpty
    }

    func makeCoordinator() -> Coordinator {
        Coordinator(text: $text, hasContent: $hasContent)
    }

    class Coordinator: NSObject, UITextViewDelegate {
        @Binding var text: String
        @Binding var hasContent: Bool

        init(text: Binding<String>, hasContent: Binding<Bool>) {
            _text = text
            _hasContent = hasContent
        }

        func textViewDidChange(_ textView: UITextView) {
            text = textView.text
            hasContent = !text.isEmpty
        }
    }
}

2. 修正父视图Input的绑定传递

确保向TextInputView传递绑定值,并在按钮点击事件中直接清空content:

struct Input: View {
    @State var content: String = ""
    var hint: String = ""
    @State private var style: Style = .idle
    @FocusState private var isFocused: Bool
    @State private var desiredHeight: CGFloat = 100
    @State private var hasContent: Bool = false

    var body: some View {
        HStack {
            VStack(alignment: .leading) {
                TextInputView(
                    text: $content,
                    desiredHeight: $desiredHeight,
                    hasContent: $hasContent
                )
                .focused($isFocused)
                .onChange(of: isFocused) { isFocused in
                    withAnimation {
                        style = isFocused ? .focused : .idle
                    }
                }
            }
            Button {
                // 直接清空绑定的content即可
                content = ""
            } label: {
                Text("Press Me")
            }
            .hidden(!(hasContent && isFocused))
            .padding(.trailing, 16)
        }
    }

    enum Style {
        case idle, focused
    }
}

关键说明

  • 使用@Binding建立父视图与子视图的双向数据同步,确保清空content时,UITextView的文本会同步更新
  • 在updateUIView中加入文本判断,避免UITextView内容变化时触发无限循环更新
  • 通过hasContent的双向绑定,确保清除按钮的显示隐藏状态与文本内容同步

内容的提问来源于stack exchange,提问作者The clear button awaits

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.29 18:47:10