13
votes

My problem is that programmatically setting the selectedRange of UITextView selects the text, but does not visually indicate it's selected. Does this sound like a bug in OS 3.0/3.1. More importantly, any solution or suggestions for getting the selection to display? (sample project linked at bottom of message)

How do I know it's selected since I'm not getting visual feedback? Two reasons:

  1. No blinking cursor
  2. Tapping any key on keyboard deletes existing text in the selection range.

I have a UITextView in a viewcontroller which allows editing a user-changeable value. The editor controller is opened when a double-tap is received on a table row, or the user taps the detail disclosure button on a row. The viewcontroller arrives via presentModalViewController, and in the editor VC's viewWillAppear method, I initiate the keyboard with [self.textView becomeFirstResponder];

At times I want to start the editor with the entire contents of the textview selected so the user could simply start typing and it would delete the existing contents (this is because I create new items with default titles so it's almost certain the user will first delete the entire contents of the editor text field, then type their title).

Some of the things I've tried already:

  1. setting the selected range in viewDidAppear (instead of and in addition to doing it in textViewDidBeginEditing).
  2. Replacing _textView.text with a copy of the text in it then applying the selectedRange (in textViewDidBeginEditing)... thinking maybe if I'm dealing with framework bug, this might get around it.
  3. [[_textView webView] selectAll]; (private api). same behavior, text gets selected with no visual feedback.
  4. sending _textView setNeedsDisplay and setNeedsLayout.
  5. using a performSelector ... afterDelay to set the selectedRange so that it happens after exiting textViewDidBeginEditing.

refs on S.O.: Here and here

// UITextFieldDelegate Methods...
- (void)textViewDidBeginEditing:(UITextView *)_textView
{
 NSInteger len = [_textView.text length];

 if( self.selectInitialText ){
  //NOTE: this is not working as expected. Indeed the text is 
  // selected but the highlighting of the text isn't showing.
  _textView.selectedRange = NSMakeRange(0,len);
 }
}

-- EDIT --
Here's the sample project submitted to Apple BugReporter. Download BugReport_7380723 sample project

Additional Information:

While creating and playing with the sample project submission, I discovered two things:

  • When there's text selected but no highlight displayed, tap some keystrokes then "shake to undo" and the original text is restored but IS highlighted.

  • If you manually make a selection in the textview, then tap the "Select All" button [refers to the sample project linked above], all text is selected AND displays the highlight properly.

4

4 Answers

17
votes

Before setting the selection programmatically on the textView, just call select to make it show the new selection visually. For example:

[textView select:self];
textView.selectedRange = newSelectedRange; 
4
votes

I'll answer my own question for now and update it later when there's more info (or if someone else finds a suitable work around, I'll happily move the check to their answer). I've got a bug report into apple and after submitting sample code, it's sitting there with open status. I'm pretty confident it's a bug, so when I get a response from them, I'll pass along here.

1
votes

Suddenly meet this question. I've had the same problem until I check NSObject's declare header. They 've already provided a function named selectAll:

@interface NSObject(UIResponderStandardEditActions)   // these methods are not implemented in NSObject

- (void)cut:(id)sender __OSX_AVAILABLE_STARTING(__MAC_NA,__IPHONE_3_0);
- (void)copy:(id)sender __OSX_AVAILABLE_STARTING(__MAC_NA,__IPHONE_3_0);
- (void)paste:(id)sender __OSX_AVAILABLE_STARTING(__MAC_NA,__IPHONE_3_0);
- (void)select:(id)sender __OSX_AVAILABLE_STARTING(__MAC_NA,__IPHONE_3_0);
- (void)selectAll:(id)sender __OSX_AVAILABLE_STARTING(__MAC_NA,__IPHONE_3_0);
- (void)delete:(id)sender __OSX_AVAILABLE_STARTING(__MAC_NA,__IPHONE_3_2);

@end
0
votes

Workaround: What you seem to want is UITextView placeholder functionality. This of course does not exist. However, there are some workarounds here