Clear Button UITextView

I have a view that has a UITextView and I need to add a clear button. However, I cannot wrap my head around it. I tried multiple approaches but none seemed to work. I need to know what I should write inside the button in order to clear the text of TextInputview

This is a minimal reproducible example:

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

    var body: some View {
        HStack {
            VStack(alignment: .leading) {
                TextInputView(text: content, desiredHeight: self.$desiredHeight, hasContent: $hasContent)
                    .focused($isFocused)
                    .onChange(of: isFocused) { isFocused in
                        withAnimation {
                            style = isFocused ? .focused : .idle
                        }
                    }
            }
            Button {
                // I need to know what to insert here
            } label: {
                Text("Press Me")
            }   .hidden(!(hasContent && isFocused))
                .padding(.trailing, Constants.paddingHorizontal)    
        }
    }
}
struct TextInputView: UIViewRepresentable {
    
    @State var text: String
    var foregroundColor: Color = .grey

    func makeUIView(context: UIViewRepresentableContext<TextInputView>) -> UITextView {
        let view = UITextView()
        view.font = font.uiFont
        view.textColor = .init(foregroundColor)
        view.isEditable = true
        view.isScrollEnabled = true
        view.delegate = context.coordinator
        return view
    }

    func updateUIView(_ uiView: UITextView, context _: UIViewRepresentableContext<TextInputView>) {
        uiView.text = text
        uiView.textColor = .init(foregroundColor)
    }

    func makeCoordinator() -> Coordinator {
        return Coordinator(text: $text, parent: self)
    }

    class Coordinator: NSObject, UITextViewDelegate {
        @Binding var text: String
        @Binding var parent: TextInputView
        init(text: Binding<String>, parent: TextInputView) {
            _text = text
            _parent = .constant(parent)
        }

        func textViewDidBeginEditing(_ textView: UITextView) {
            textView.becomeFirstResponder()
        }

        func textViewDidChange(_ textView: UITextView) {
            text = textView.text
        }
        
        func textViewDidEndEditing(_ textView: UITextView) {
            
        }
    }
}

I tried to just to self.content = ""; I tried to use dispatch queues, I tried to trigger a onpreferencesChange.

Some solutions suggest outlets but I can’t figure out how to use them and failed every time

>Solution :

The problem is due to the fact that the input String is defined twice as @State. It should be marked as@Binding in TextInputView. This way the value is linked between the two views and change in one (i.e. Input) is reflected in the other (i.e. TextInputView). That’s how it would look simplified:

struct ContentView: View {
    
    @State var content: String = ""
    
    var body: some View {
        HStack {
            TextInputView(text: $content)
            Button {
                content = ""
            } label: {
                Text("Press Me")
            }
        }
    }
}

struct TextInputView: UIViewRepresentable {
    
    @Binding var text: String

    func makeUIView(context: UIViewRepresentableContext<TextInputView>) -> UITextView {
        // etc. ...

Leave a Reply