Follow-up, but related question. I expanded my demo, playing with TextField(text:selection) to understand it and found that the selection changes before the text does.
Below is my expanded file. I tried to print the selection underneith the TextField but this code crashes. I've added print statements to debug and found that the selection is not valid for the value of text when I call toString. Is this normal?
I found that using the onChange event on the selection works correctly but I see this as a workaround. It means there is currently no way to just print the selection (current state) with the corresponding text (same state) in the view, or am I missing something?
struct ContentView: View {
@State private var selection: TextSelection?
@State private var text: String = ""
var body: some View {
VStack {
TextField("Message", text: $text, selection: $selection)
// .onChange(of: selection) {
// if let selection = selection.take() {
// if case let .selection(range) = selection.indices {
// print("Selection in \(text): \(toString(selection: selection))")
// print("Selected text: '\(text[range])'")
// }
// }
// }
Text("Selection in \(text): \(toString(selection: selection))")
}
.padding()
}
func toString(selection: TextSelection?) -> String {
guard let selection else { return "None" }
print("Printing indices in '\(text)'")
switch selection.indices {
case .selection(let range):
let lower = range.lowerBound.utf16Offset(in: text)
let upper = range.upperBound.utf16Offset(in: text)
return "\(lower) - \(upper)"
case .multiSelection(let rangeSet):
return "Multi selection \(rangeSet)"
@unknown default:
fatalError("Unknown selection")
}
}
}