Text jumping (I don't know how else to name that weird behavior) to the top(?) every time user enters a new character. I can reproduce the issue only on iPad OS 16. It affects the user who attempts to write long (several paragraphs) text in the TextEditor.
Reproduced with following code (just past five or more paragraphs of Lorem Ipsum and start typing)
class EditorViewModel: ObservableObject {
@Published var text: String = ""
}
struct EditorView: View {
@ObservedObject var viewModel: EditorViewModel
var body: some View {
VStack {
TextEditor(text: $viewModel.text)
.frame(height: 80)
.padding()
.background(Color.red)
Spacer()
}
}
}
struct ContentView: View {
var body: some View {
EditorView(
viewModel: EditorViewModel()
)
}
}
I've likely fiddled with every possible setting in TextEditor
to no avail. Can't believe I had to resort to UIViewRepresentable
to fix this issue in 2024.
Tested with a continuous input of ~5000 characters with no bouncing on iPadOS 17.4.
struct TextViewWrapper: UIViewRepresentable {
@Binding var text: String
func makeUIView(context: Context) -> UITextView {
let textView = UITextView()
textView.delegate = context.coordinator
return textView
}
func updateUIView(_ uiView: UITextView, context: Context) {
uiView.text = text
}
func makeCoordinator() -> Coordinator {
Coordinator(self)
}
class Coordinator: NSObject, UITextViewDelegate {
var parent: TextViewWrapper
init(_ parent: TextViewWrapper) {
self.parent = parent
}
func textViewDidChange(_ textView: UITextView) {
parent.text = textView.text
}
}
}
Edit:
func updateUIView(_ uiView: UITextView, context: Context) {
let selectedRange = uiView.selectedRange
uiView.text = text
uiView.selectedRange = selectedRange
}
selectedRange to be applied to avoid cursor being bounced to the last of the full text when attempting to insert a next line anywhere within the text