Getting and Setting Cursor Position of UITextField and UITextView in Swift Getting and Setting Cursor Position of UITextField and UITextView in Swift ios ios

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.