Getting and Setting Cursor Position of UITextField and UITextView in Swift
The following content applies to both UITextField
and UITextView
.
Useful information
The very beginning of the text field text:
let startPosition: UITextPosition = textField.beginningOfDocument
The very end of the text field text:
let endPosition: UITextPosition = textField.endOfDocument
The currently selected range:
let selectedRange: UITextRange? = textField.selectedTextRange
Get cursor position
if let selectedRange = textField.selectedTextRange { let cursorPosition = textField.offset(from: textField.beginningOfDocument, to: selectedRange.start) print("\(cursorPosition)")}
Set cursor position
In order to set the position, all of these methods are actually setting a range with the same start and end values.
To the beginning
let newPosition = textField.beginningOfDocumenttextField.selectedTextRange = textField.textRange(from: newPosition, to: newPosition)
To the end
let newPosition = textField.endOfDocumenttextField.selectedTextRange = textField.textRange(from: newPosition, to: newPosition)
To one position to the left of the current cursor position
// only if there is a currently selected rangeif let selectedRange = textField.selectedTextRange { // and only if the new position is valid if let newPosition = textField.position(from: selectedRange.start, offset: -1) { // set the new position textField.selectedTextRange = textField.textRange(from: newPosition, to: newPosition) }}
To an arbitrary position
Start at the beginning and move 5 characters to the right.
let arbitraryValue: Int = 5if let newPosition = textField.position(from: textField.beginningOfDocument, offset: arbitraryValue) { textField.selectedTextRange = textField.textRange(from: newPosition, to: newPosition)}
Related
Select all text
textField.selectedTextRange = textField.textRange(from: textField.beginningOfDocument, to: textField.endOfDocument)
Select a range of text
// Range: 3 to 7let startPosition = textField.position(from: textField.beginningOfDocument, offset: 3)let endPosition = textField.position(from: textField.beginningOfDocument, offset: 7)if startPosition != nil && endPosition != nil { textField.selectedTextRange = textField.textRange(from: startPosition!, to: endPosition!)}
Insert text at the current cursor position
textField.insertText("Hello")
Notes
Use
textField.becomeFirstResponder()
to give focus to the text field and make the keyboard appear.See this answer for how to get the text at some range.
See also
In my case I had to use DispatchQueue:
func textViewDidBeginEditing(_ textView: UITextView) { DispatchQueue.main.async { textField.selectedTextRange = ... }}
Nothing else from this and other threads worked.
PS: I double checked which thread did textViewDidBeginEditing was running on, and it was main thread, as all UI should run on, so not sure why that little delay using main.asynch worked.
For set cursor position at your point:
textView.beginFloatingCursor(at: CGPoint(x: 10.0, y: 10.0))
For reset cursor position:
textView.endFloatingCursor()
Note: This example works in both Textview & Textfield.