Getting and Setting Cursor Position of UITextField and UITextView in Swift
Interview Questions practice on Codemia
Over 8,000 real interview questions from top companies, searchable by company and role.
Introduction
In UIKit, cursor position is not exposed as a plain integer property. UITextField and UITextView work through the UITextInput API, which represents caret and selection positions with UITextPosition and UITextRange. Once you understand that model, reading and updating the caret becomes predictable and reusable.
Read the Current Cursor Position
The usual pattern is to read selectedTextRange and measure the offset from beginningOfDocument.
This works for both controls because they both conform to UITextInput.
If the selection is collapsed, that offset is the caret position. If the user has highlighted text, it is the start of the selection range.
Set the Cursor Position
To place the cursor at a specific offset, create a UITextPosition from the document start and assign a collapsed selectedTextRange.
Always guard the offset because text may be shorter than expected after editing or formatting.
Preserve the Caret While Reformatting Text
A common use case is text formatting, such as adding spaces to a credit-card input. Without explicit cursor management, the caret usually jumps to the end.
That pattern makes typing feel stable instead of erratic.
Remember That Selection Is Not Always a Caret
selectedTextRange may represent a selection rather than a single insertion point. If your code assumes a collapsed caret, verify that start and end are the same.
This matters for mention insertion, autocomplete, or replace operations. Overwriting the user’s selection when you thought you were moving only the caret produces frustrating editing bugs.
Main-Thread and Timing Considerations
Text selection updates belong on the main thread. In some delegate callbacks, setting the selection immediately can conflict with UIKit’s own text updates. If that happens, scheduling the cursor change on the next run loop can help.
Use that only when necessary. It is a workaround for timing, not the default pattern.
Common Pitfalls
- Treating cursor position as a plain integer property instead of using
UITextPositionandUITextRange. - Setting a caret offset that is outside the current text bounds.
- Forgetting that
selectedTextRangemay represent a selection rather than a collapsed caret. - Updating selection before the text change has finished, which causes visible cursor jumps.
Summary
- Read caret position using
selectedTextRangeandbeginningOfDocument. - Set caret position by creating a
UITextPositionand collapsedUITextRange. - The same pattern works for both
UITextFieldandUITextView. - Preserve cursor position explicitly when reformatting text.
- Validate offsets and keep selection updates on the main thread.
Related reading
- Getting and Setting Cursor Position of UITextField and UITextView in Swift
- Getting current device language in iOS?
- Getting device orientation in Swift
- Getting error No such module using Xcode, but the framework is there
- Getting error No such module using Xcode, but the framework is there
- getting exception IllegalStateException Can not perform this action after onSaveInstanceState
- Getting “INTERNAL” exception when an async Firebase function is called from android app
- Getting reference to the top-most view/window in iOS application
.png&w=3840&q=75)
Tackling System Design Interview Problems
A short course that equips you with the skills to approach system design interviews methodically.
Start the free courseTrack what you have practised
A free account saves your progress, solutions and study plan across every problem on Codemia.
Interview Questions practice on Codemia
Over 8,000 real interview questions from top companies, searchable by company and role.