3

I am editing text in a UITextView. When the field opens for editing I need the cursor to be positioned after the final character of the existing text. The behavior I see is that the cursor is positioned more or less under the point where I touch the UITextView to start editing -- perhaps at the end of the word I touch on. I have tried setting the textview.selectedRange in both textViewDidBeginEditing: and textViewShouldBeginEditing: but that had no effect at all. I tried selecting ranges of the existing text, like {1,2} and that didn't do anything either. It seems like the selectedRange is more-or-less a read-only value?

- (void) textViewDidBeginEditing:(UITextView *)textView {
    // Position the insertion cursor at the end of any existing text
    NSRange insertionPoint = NSMakeRange([textView.text length], 0);
    textView.selectedRange = insertionPoint;
}

How do I get the cursor to the end of the text?

Charlie Price
  • 1,266
  • 11
  • 20
  • Take a look the answer is here: http://stackoverflow.com/questions/10135086/how-to-set-cursor-position-for-uitextview-on-user-input – artud2000 Dec 04 '13 at 20:28
  • Thanks artud2000. The answer that works for me is to put a UITapGestureRecognizer on the UITextView and in the tap handler to set the text view to be the first responder. The "natural" position of the cursor in this case is at the end of the existing text. – Charlie Price Dec 04 '13 at 21:07
  • Yes sometimes is necessary to write code that will trigger or detect events in top of the usual behaviour of UIControl elements. – artud2000 Dec 05 '13 at 16:47

2 Answers2

1

The post referred to by the comment by artud2000 contains a working answer. To summarize here, add:

EDIT: The original answer was not sufficient. I've added toggling the editable property which seems to be sufficient. The problem is that the tap gesture only goes to the handler a single time (at most) and subsequent taps on the UITextField start editing directly. If it isn't editable then the UITextView's gesture recognizers are not active and the one I placed will work. This may well not be a good solution but it does seem to work.

- (void)viewDidLoad {
...
    tapDescription = [[UITapGestureRecognizer alloc] 
        initWithTarget:self action:@selector(tapDescription:)];
    [self.descriptionTextView addGestureRecognizer:tapDescription];
    self.descriptionTextView.editable = NO;  // if not set in storyboard
}

- (void) tapDescription:(UIGestureRecognizer *)gr {
    self.descriptionTextView.editable = YES;
    [self.descriptionTextView becomeFirstResponder];
}

- (void) textViewDidEndEditing:(UITextView *)textView {
    //whatever else you need to do
    textView.editable = NO;
}

The default position of the cursor seems to be after any existing text which solved my problem, but if you want to you can select the text in textViewDidBeginEditing: by setting the selectedRange -- for instance:

- (void) textViewDidBeginEditing:(UITextView *)textView {
    // Example: to select the second and third characters when editing starts...
    NSRange insertionPoint = NSMakeRange(1, 2);
    textView.selectedRange = insertionPoint;
}
Charlie Price
  • 1,266
  • 11
  • 20
0

Thanks for the answer Charlie Price. I used it to solve my similar problem on a UITextView. Here's the answer in Swift in case anyone needs it:

...
    let tapDescription = UITapGestureRecognizer(target: self, action: #selector(MyViewController.tapDescription(_:)))
    self.descriptionTextView.addGestureRecognizer(tapDescription)
    self.descriptionTextView.editable = false
...

    func tapDescription(gr: UIGestureRecognizer) {
        self.descriptionTextView.editable = true
        self.descriptionTextView.becomeFirstResponder()
    }

    func textViewDidEndEditing(textView: UITextView) {
        self.descriptionTextView.editable = false
    }
Hellojeffy
  • 1,851
  • 2
  • 19
  • 23