Search code examples
iosswiftuitextfielduitextviewuitextposition

Getting and Setting Cursor Position of UITextField and UITextView in Swift


I've been experimenting with UITextField and how to work with it's cursor position. I've found a number of relation Objective-C answers, as in

But since I am working with Swift, I wanted to learn how to get the current cursor location and also set it in Swift.

The answer below is the the result of my experimentation and translation from Objective-C.


Solution

  • 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.beginningOfDocument
    textField.selectedTextRange = textField.textRange(from: newPosition, to: newPosition)
    

    To the end

    let newPosition = textField.endOfDocument
    textField.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 range
    if 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 = 5
    if 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 7
    let 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