I'm trying to implement a feature whereby a user can tap a button to insert a character at the cursor in a TextField - the cursor then needs to be moved forward to be in front of the insert character.
I'm having trouble with characters such as π which are UTF16 encoded.
In the following sample app, enter the following sequence:
- Enter
9by keyboard - tap
+ - Enter
9by keyboard - tap
π - Enter
9via keyboard - tap
+
he TextField will show '9+9π+9' (i.e. the final + is inserted before 9 rather than after it. Any insight into what I am doing wrong?
import SwiftUI
@main
struct TextInsertApp: App {
var body: some Scene {
WindowGroup {
ContentView()
}
}
}
struct ContentView: View {
@State private var text: String = ""
@State private var selection: TextSelection? = nil
var body: some View {
TextField("", text: $text, selection: $selection)
.background(.gray.opacity(0.4))
Button("+") { insert("+") }
Button("π") { insert("π") }
}
func insert(_ insertString: String) {
if let selection {
if case let .selection(range) = selection.indices {
if selection.isInsertion {
text.insert(contentsOf: insertString, at: range.lowerBound)
} else {
text.replaceSubrange(range, with: insertString)
}
let cursor = text.utf16.index(range.upperBound, offsetBy: insertString.count)
self.selection = .init(insertionPoint: cursor)
}
} else {
text += insertString
selection = .init(range: text.utf16.endIndex..<text.utf16.endIndex)
}
}
}