Folks, I'm trying to understand what I'm missing here. In a SwiftUI project, I've wrapped a UITextView in UIViewRepresentable as a replacement for SwiftUI's TextEditor control, largely so that I can get it to become/resign first responder status.
This minimally-viable example works fine, except for one bug that I can't seem to resolve: if I add an emoji anywhere in that text view, then text insertion goes haywire — wherever I have the cursor, the character typed will be inserted, but then the cursor immediately jumps to the end of the text in the field.
Credit to this Stack Overflow answer for the above code: https://stackoverflow.com/a/56508132
Can someone help me understand what I'm doing wrong?
There's an example project available here, wrapping both UITextField and UITextView in UIViewRepresentable: https://github.com/AngeloStavrow/WrappedTextInputExample
This minimally-viable example works fine, except for one bug that I can't seem to resolve: if I add an emoji anywhere in that text view, then text insertion goes haywire — wherever I have the cursor, the character typed will be inserted, but then the cursor immediately jumps to the end of the text in the field.
Code Block swift import SwiftUI struct WrappedTextView: UIViewRepresentable { class Coordinator: NSObject, UITextViewDelegate { @Binding var text: String var didBecomeFirstResponder: Bool = false init(text: Binding<String>) { _text = text } func textViewDidChangeSelection(_ textView: UITextView) { DispatchQueue.main.async { self.text = textView.text ?? "" } } } @Binding var text: String var isFirstResponder: Bool = false func makeUIView(context: UIViewRepresentableContext<WrappedTextView>) -> UITextView { let textView = UITextView() textView.delegate = context.coordinator return textView } func makeCoordinator() -> WrappedTextView.Coordinator { return Coordinator(text: $text) } func updateUIView(_ uiView: UIViewType, context: UIViewRepresentableContext<WrappedTextView>) { uiView.text = text if isFirstResponder && !context.coordinator.didBecomeFirstResponder { uiView.becomeFirstResponder() context.coordinator.didBecomeFirstResponder = true } } }
Credit to this Stack Overflow answer for the above code: https://stackoverflow.com/a/56508132
Can someone help me understand what I'm doing wrong?
There's an example project available here, wrapping both UITextField and UITextView in UIViewRepresentable: https://github.com/AngeloStavrow/WrappedTextInputExample
Okay, this bug can be resolved if you make the following change to the updateUIView(_: context:) function:
Code Block swift func updateUIView(_ uiView: UIViewType, context: UIViewRepresentableContext<WrappedTextView>) { if (uiView.text != text) { uiView.text = text } if isFirstResponder && !context.coordinator.didBecomeFirstResponder { uiView.becomeFirstResponder() context.coordinator.didBecomeFirstResponder = true } }