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. ...