Ethan G Ethan G - 1 month ago 12
iOS Question

UITextView selectAll method not working as expected

I'm creating an iOS 8 app with Xcode 6.0.1 for my iPhone 5 (which has iOS 8.0.2 on it). I want to make it so that when a user clicks on my

UITextView
, all the text gets selected so he can easily start typing and erase what was there (but I don't want the text to be automatically erased because the user may want to keep it or append to it). To do this, I have the following code:

- (void)textViewDidBeginEditing:(UITextView *)textView {
if ([textView hasText]) {
NSLog(@"selectedRange before: %d", textView.selectedRange.length);
[textView selectAll:self];
NSLog(@"selectedRange after: %d", textView.selectedRange.length);
}
}


When this method gets called, the console output is what I expect (i.e. the
selectedRange
length is the same as the number of characters in the
textView
's text). However, nothing shows up as selected in the
UITextView
and it doesn't act selected (i.e. no selection menu pops up).

I have seen multiple questions like this on the internet, but none of the provided solutions worked for me (and some of them wrote it off as a bug without providing any solution). Changing the sender id to something other than
self
(such as
nil
) did not help, and neither did it help to call
[textView select:self]
as one person suggested. I have also tried this code:

- (void)textViewDidBeginEditing:(UITextView *)textView {
if ([textView hasText]) {
UITextRange *range = [textView textRangeFromPosition:textView.beginningOfDocument toPosition:textView.endOfDocument];
[textView setSelectedTextRange:range];
}
}


But, it has the same problem.

Any suggestions?

Answer

The best solution I've found for this issue so far is to create a custom UITextView (i.e. create a new class that extends UITextView) and then implement the selectAll method like this:

- (void)selectAll:(id)sender {
    [super selectAll:sender];
    UITextRange *selectionRange = [self textRangeFromPosition:self.beginningOfDocument toPosition:self.endOfDocument];
    [self performSelector:@selector(setSelectedTextRange:) withObject:selectionRange afterDelay:0.0];
}

Then when you use a text view, set its type to your custom text view type (in your code and in the storyboard). Now you can successfully call the selectAll method whenever you need to. I suppose this should work with UITextField too, but I haven't tried it yet.