I’m depending on the TextView using UIViewRepresentable created here https://www.appcoda.com/swiftui-textview-uiviewrepresentable/.
struct TextView: UIViewRepresentable {
@Binding var text: String
@Binding var textStyle: UIFont.TextStyle
func makeUIView(context: Context) -> UITextView {
let textView = UITextView()
textView.delegate = context.coordinator
textView.font = UIFont.preferredFont(forTextStyle: textStyle)
textView.autocapitalizationType = .sentences
textView.isSelectable = true
textView.isUserInteractionEnabled = true
return textView
}
func updateUIView(_ uiView: UITextView, context: Context) {
uiView.text = text
uiView.font = UIFont.preferredFont(forTextStyle: textStyle)
}
func makeCoordinator() -> Coordinator {
Coordinator($text)
}
class Coordinator: NSObject, UITextViewDelegate {
var text: Binding<String>
init(_ text: Binding<String>) {
self.text = text
}
func textViewDidChange(_ textView: UITextView) {
self.text.wrappedValue = textView.text
}
}
}
struct ContentView: View {
@State private var message = ""
@State private var textStyle = UIFont.TextStyle.body
var body: some View {
ZStack(alignment: .topTrailing) {
TextView(text: $message, textStyle: $textStyle)
.padding(.horizontal)
Button(action: {
self.textStyle = (self.textStyle == .body) ? .title1 : .body
}) {
Image(systemName: "textformat")
.imageScale(.large)
.frame(width: 40, height: 40)
.foregroundColor(.white)
.background(Color.purple)
.clipShape(Circle())
}
.padding()
}
}
}
The problem I’m having is whenever I start a newline 1) before the final line + 2) after the last character on the line, the cursor always jumps to after the final character in the text. Any ideas?
UPDATE:
Leo’s response technically addresses this issue, but it doesn’t seem perfect as there’s undesired scroll behaviour whereby although the caret position is now correct that doesn’t stop an auto-scroll to the bottom. See below:
You can save the caret position (selectedRange) and set your text view selected range after setting the text property inside updateUIView method: