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