25

I have a UITextField in my iPhone app. I know how to make the text field select all of its text, but how can change the selection? Say I wanted to select the last 5 characters, or a specific range of characters, is that possible? if not, can I move the lines marking the beginning and end of the selection, as if the user is dragging them?

Sunian314
  • 329
  • 1
  • 4
  • 11
  • Hey.. Can you show me how to make the text field select all of its text – Ajay Sharma Jun 20 '12 at 06:48
  • @AjaySharma, [Select all text in text field](http://stackoverflow.com/a/34922831/3681880) (I'm sure you no longer need to know, but no one else had answered this comment, yet.) – Suragch Jan 21 '16 at 11:45

7 Answers7

32

With UITextField, you cannot. But if you see the headers, you have _selectedRange and others that might be used if you add some categories to it ;)


Update for iOS5 and above :

Now UITextField and UITextView conform to UITextInput protocol so it is possible :)

Selecting the last 5 characters before the caret would be like this:

// Get current selected range , this example assumes is an insertion point or empty selection
UITextRange *selectedRange = [textField selectedTextRange];

// Calculate the new position, - for left and + for right
UITextPosition *newPosition = [textField positionFromPosition:selectedRange.start offset:-5];

// Construct a new range using the object that adopts the UITextInput, our textfield
UITextRange *newRange = [textField textRangeFromPosition:newPosition toPosition:selectedRange.start];

// Set new range
[textField setSelectedTextRange:newRange];
Community
  • 1
  • 1
nacho4d
  • 43,720
  • 45
  • 157
  • 240
  • I don't really understand what you mean. since you said it's not possible with text fields, I tried using a textview, which does have a selectedRange field, though I can't seem to get either the getter or setter to work. for example: txtDescription.selectedRange = NSMakeRange(0, 5); I was hoping this would select the first 5 characters in txtDescription, which is a UITextView*, but it doesn't. any ideas? – Sunian314 Jul 19 '10 at 12:53
  • nevermind, I solved my problem with a different approach not involving text selection. thanks for your advice anyway. – Sunian314 Jul 19 '10 at 14:51
  • BTW, selectedRange works when the textView is first responder (when is editing for example.) Ask for selectedRange and you will get the cursor position or selection range if there is a selection. Set it and the cursor will change ;) – nacho4d Jul 21 '10 at 03:08
  • 1
    @Sunian314 : Hi, will you show what approach did solve your problem? – iCoder86 Mar 08 '11 at 09:22
  • what I was really trying to do was add text completion functionality to a text field that mimics what the address bar in your browser does, so if the user types "He" and they had previously entered "Hello", then "Hello" would show up in the textfield, but the "llo" at the end would be selected so that the user could keep typing in case he meant something else. Since I couldn't get that to work, I decided to create a button that pops up with the remaining letters of the completion, so in this case, a button would popup with the text "llo" that the user could tap to drop those letters in. – Sunian314 Mar 08 '11 at 15:09
  • @Sunian314 Hi.. Can you show me how did you got text selection with iOS 4.2.Using the above code, my app gets crash. – Ajay Sharma Jun 20 '12 at 06:43
  • I'm using this code on iOS 6.1 but the keyboard keeps returning to "Capital Letter Mode" after the selection. Does this happens to anyone else? On iOS 7 it doesn't happen. – Jão Dec 29 '13 at 07:06
13

To select a specific range of characters you can do something like this in iOS 5+

int start = 2;
int end = 5;
UITextPosition *startPosition = [self positionFromPosition:self.beginningOfDocument offset:start];
UITextPosition *endPosition = [self positionFromPosition:self.beginningOfDocument offset:end];
UITextRange *selection = [self textRangeFromPosition:startPosition toPosition:endPosition];
self.selectedTextRange = selection;

Since UITextFields and other UIKit elements have their own private subclasses of UITextPosition and UITextRange you can not create new values directly, but you can use the text field to create them for you from a reference to the beginning or end of the text and an integer offset.

You can also do the reverse to get integer representations of the start and end points of the current selection:

int start = [self offsetFromPosition:self.beginningOfDocument toPosition:self.selectedTextRange.start];
int end = [self offsetFromPosition:self.beginningOfDocument toPosition:self.selectedTextRange.end];

Here is a category which adds methods to handle selections using NSRanges. https://gist.github.com/4463233

Anthony Mattox
  • 7,048
  • 6
  • 43
  • 59
5

To select the name of a file without the file extension, use this:

-(void) tableViewCellDidBeginEditing:(UITableViewTextFieldCell*) cell
{
    NSInteger fileNameLengthWithoutExt = [self.filename length] - [[self.filename pathExtension] length];
    UITextField* textField = cell.textField;
    UITextPosition* start = [textField beginningOfDocument];
    UITextPosition* end = [textField positionFromPosition:start offset: fileNameLengthWithoutExt - 1]; // the -1 is for the dot separting file name and extension
    UITextRange* range = [textField textRangeFromPosition:start toPosition:end];
    [textField setSelectedTextRange:range];
}
Pang
  • 9,564
  • 146
  • 81
  • 122
orkoden
  • 18,946
  • 4
  • 59
  • 50
  • 1
    The code would probably be simpler by using `self.filename.stringByDeletingPathExtension.length` instead of `[self.filename length] - [[self.filename pathExtension] length] - 1`. – Pang Jul 18 '17 at 08:59
3

These both work for me:

[UITextField selectAll:self];

and:

UITextField.selectedRange = NSMakeRange(0, 5);

but only if the text field is the first responder. (In other words, only if the keyboard is showing.) So, you need to precede either of the select methods with this:

[UITextField becomeFirstResponder];

if you want the text to appear selected.

cetcet
  • 2,147
  • 2
  • 15
  • 15
  • This appears to be true of `UITextView` but not `UITextField`. Or do you know something I don't? – jab Dec 09 '11 at 01:37
  • 3
    `selectAll:` is part of the UIResponderStandardEditActions informal protocol, which UITextField adopts. `selectedRange` is not a property of `UITextField`, though `selectedTextRange` is, as nacho4d's update above covers. –  Apr 13 '12 at 13:12
1

Just a small addition to the accepted answer. In iOS 5, the following line crashes my app when UITextView's text length is 0 (has no text):

[self textRangeFromPosition:startPosition toPosition:endPosition];

A small workaround is to add a length == 0 check like:

if (textField.text && textField.text.length > 0) {
    // Get current selected range , this example assumes is an insertion point or empty selection
    UITextRange *selectedRange = [textField selectedTextRange];

    // Calculate the new position, - for left and + for right
    UITextPosition *newPosition = [textField positionFromPosition:selectedRange.start offset:-5];

    // Construct a new range using the object that adopts the UITextInput, our textfield
    UITextRange *newRange = [textField textRangeFromPosition:newPosition toPosition:selectedRange.start];

    // Set new range
    [textField setSelectedTextRange:newRange];
}
Pang
  • 9,564
  • 146
  • 81
  • 122
Stanislav Pankevich
  • 11,044
  • 8
  • 69
  • 129
0

Swift

Select the last 5 characters:

if let newPosition = textField.positionFromPosition(textField.endOfDocument, inDirection: UITextLayoutDirection.Left, offset: 5) {

    textField.selectedTextRange = textField.textRangeFromPosition(newPosition, toPosition: textField.endOfDocument)
}

Select an arbitrary range:

// Range: 3 to 7
let startPosition = textField.positionFromPosition(textField.beginningOfDocument, inDirection: UITextLayoutDirection.Right, offset: 3)
let endPosition = textField.positionFromPosition(textField.beginningOfDocument, inDirection: UITextLayoutDirection.Right, offset: 7)

if startPosition != nil && endPosition != nil {
    textField.selectedTextRange = textField.textRangeFromPosition(startPosition!, toPosition: endPosition!)
}

My full answer is here.

Community
  • 1
  • 1
Suragch
  • 484,302
  • 314
  • 1,365
  • 1,393
0

Swift 5.0

here is how I selecte file name Panda from Panda.txt

func textFieldDidBeginEditing(_ textField: UITextField) {
    // if textField.text is `Panda.txt`, offset will be 3
    let offset = String(textField.text!.split(separator: ".").last!).length
    let from = textField.position(from: textField.beginningOfDocument, offset: 0)
    let to = textField.position(from: textField.beginningOfDocument,
                                offset:textField.text!.length - (offset+1) )
    //now `Panda` will be selected
    textField.selectedTextRange = textField.textRange(from: from!, to: to!)
}

Panway
  • 46
  • 4