UITextField selects all text on focus when the content is long — how to keep the caret at the end?

I’m building a custom input field using UITextField. When the user taps to focus the field and the text is long, the entire text becomes selected by default. This is the same behavior you can see in iOS Safari’s search field or the Messages app search field.

What I want: when the field becomes first responder, the caret should be placed at the end of the text (latest word), without selecting all the text.

Here’s the code that builds my text field:

public func makeTextField() -> UITextField {
    let textField = UITextField()

    textField.autocorrectionType = .no
    textField.setContentCompressionResistancePriority(.required, for: .horizontal)
    textField.setContentCompressionResistancePriority(.required, for: .vertical)
    if #available(iOS 13.0, *) {
        textField.smartInsertDeleteType = .no
    }
    textField.smartQuotesType = .no
    textField.smartDashesType = .no
    textField.autocapitalizationType = .none
    textField.contentMode = .scaleToFill

    if let font = attributes[.font] as? UIFont {
        textField.font = font
    }
    if let color = attributes[.foregroundColor] as? UIColor {
        textField.textColor = color
    }

    // Truncate long text at the head
    let paragraphStyle = NSMutableParagraphStyle()
    paragraphStyle.lineBreakMode = .byTruncatingHead
    textField.defaultTextAttributes[.paragraphStyle] = paragraphStyle

    textField.delegate = self
    textField.backgroundColor = .clear
    textField.addTarget(self, action: #selector(textFieldDidChange(_:)), for: .editingChanged)
    return textField
}

Entire text is selected when focusing the field if the text is long.

What I’ve tried

Forcing the caret to the end in textFieldDidBeginEditing:

func textFieldDidBeginEditing(_ textField: UITextField) {
    let end = textField.endOfDocument
    textField.selectedTextRange = textField.textRange(from: end, to: end)
}

Doing the same asynchronously (next runloop) to avoid the system overriding selection:

func textFieldDidBeginEditing(_ textField: UITextField) {
    DispatchQueue.main.async {
        let end = textField.endOfDocument
        textField.selectedTextRange = textField.textRange(from: end, to: end)
    }
}

Despite these, the system still selects all text on focus when the string is long/truncated at the head.

I've tried your code with my iOS 26.x device + Xcode 26.1 beta 2 (17B5035f) and can't reproduce the behavior. Have you tried with the latest version system and tool? I am curious if you still see the behavior there.

I'd say changing the selectedTextRange of the text field is the right way to go, but the system can indeed override the result, and so you might try to delay your change a bit. The following code makes the change 100ms later:

func textFieldDidBeginEditing(_ textField: UITextField) {
    DispatchQueue.main.asyncAfter(deadline: .now() + 0.01) {
        let end = textField.beginningOfDocument
        textField.selectedTextRange = textField.textRange(from: end, to: end)
    }
}

Best,
——
Ziqiao Chen
 Worldwide Developer Relations.

UITextField selects all text on focus when the content is long — how to keep the caret at the end?
 
 
Q