How it works
TextSelection represents the user's current selection within an editable text view — which characters are highlighted, or where the insertion point sits when nothing is highlighted. By exposing the selection as an Equatable value you can observe and store, SwiftUI lets your view react to what the user has chosen without dropping down to platform-specific text engines. Reach for it whenever you need to know whether text is selected, drive formatting controls from the selection, or coordinate UI around the user's focus inside a TextField or TextEditor.
Hold the selection in observable state
Because the selection changes as the user drags, taps, or moves the cursor, you keep it in a source of truth that SwiftUI can watch. Declare an optional
@State private var selection: TextSelection? = nil; an optional value lets the view distinguish "there is a selection" from the initial state where one hasn't been established yet.Bind it through the selection: parameter
Editable text views accept a binding to a
TextSelection?so they can report and update the selection in step with their content. Passselection: $selectiontoTextField("Note", text: $text, selection: $selection)— the same field already bound to$textnow also writes the live selection back into your state.Read the selection to drive the UI
Once the selection flows into state, treat it like any other value your view depends on. Here the body branches on
if selection != nilto showText("Text is selected")versusText("No selection"), so the interface stays in sync with what the user has highlighted in the field.Distinguish a caret from a range
TextSelectionis non-nil both when a span of characters is highlighted and when there's only a blinking insertion point, soselection != niltells you the field is being edited or focused rather than that a range is necessarily selected. Inspect the value's bounds when you need to tell an empty caret apart from a highlighted range.
if selection != nil branch's Text("Text is selected") to interpolate the bound text, e.g. Text("Selecting in: \(text)"), then long-press to select and watch the label update as the selection changes.Example & preview
Press Run live & edit to compile it in your browser — then edit the Swift on the left and the preview re-renders live.
struct TextSelectionDemo: View {
@State private var selection: TextSelection? = nil
@State private var text = "Select me with a long press"
var body: some View {
VStack(alignment: .leading, spacing: 12) {
TextField("Note", text: $text, selection: $selection)
.textFieldStyle(.roundedBorder)
if selection != nil {
Text("Text is selected")
.foregroundStyle(.secondary)
} else {
Text("No selection")
.foregroundStyle(.secondary)
}
}
.padding()
}
}