Getting and Setting Cursor Position of UITextField and UITextView in Swift
Master System Design with Codemia
Enhance your system design skills with over 120 practice problems, detailed solutions, and hands-on exercises.
Introduction
Programmatically reading or moving the text cursor is common in input-heavy iOS screens such as masked forms, chat composers, and editors. UITextField and UITextView both expose the necessary APIs through selectedTextRange, UITextPosition, and offset(from:to:), but the model is document-based rather than simple integer indexing.
How UIKit Represents Cursor Position
UIKit does not expose the caret as a raw integer property. Instead, text controls work with document positions and ranges:
- '
beginningOfDocument' - '
endOfDocument' - '
selectedTextRange' - '
position(from:offset:)'
For a plain insertion cursor, selectedTextRange.start and selectedTextRange.end are the same position. If the user has selected text, those positions differ.
Reading the Cursor Position in a UITextField
The usual pattern is to measure the offset from beginningOfDocument to the start of the current selection.
That gives you a zero-based offset that you can log, store, or reuse after formatting text.
Setting the Cursor Position in a UITextField
To move the insertion point, convert the target offset back into a UITextPosition, then build a zero-length range.
Clamping matters because offsets beyond the current text length simply fail to produce a valid position.
Doing the Same for UITextView
UITextView uses the same cursor model, so the code is almost identical.
Because both controls share the same UITextInput concepts, the main difference is usually how your screen uses them, not how cursor movement works.
Preserving Cursor Position During Formatting
One common use case is live formatting, such as inserting spaces into a phone number or currency field. Without manual cursor handling, the caret often jumps to the end after you assign new text.
In real masked-input code, you usually adjust the offset to account for inserted or removed formatting characters.
Working with Selections, Not Just a Caret
Sometimes you need to preserve a selection range rather than a single insertion point. The same idea applies: convert offsets into positions and create a range between them.
That is useful for editor-like features, mentions, or guided text replacement.
Common Pitfalls
The most common mistake is treating cursor position as raw string indexing and ignoring UIKit's document position APIs. Another is setting text and expecting the old cursor position to survive automatically. Developers also forget to clamp offsets, which makes position creation fail silently. In formatted inputs, restoring the old offset without accounting for inserted separators can still produce a cursor jump, so offset adjustment logic needs to match the formatter.
Summary
- '
UITextFieldandUITextViewexpose cursor control throughselectedTextRangeand document positions.' - Use
offset(from:to:)to read the current cursor position. - Use
position(from:offset:)plustextRange(from:to:)to set the cursor or selection. - Clamp offsets to valid text length before restoring positions.
- Preserve and adjust cursor state explicitly when modifying text programmatically.

