8

The following code changes "test" in the textView's string to red color but it also has the effect of moving the cursor to the end of the text block when textViewDidChange is called (Aka when any text editing is made which is very annoying).

How can I prevent the cursor moving when I setAttributedText in textViewDidChange?

- (void)textViewDidChange:(UITextView *)textView {

    NSString* currentString = self.textView.text;
    NSMutableAttributedString* string = [[NSMutableAttributedString alloc]initWithString:currentString];
    NSArray *words=[currentString componentsSeparatedByString:@" "];

    for (NSString *word in words) {
        if ([word isEqualToString:@"test"]) {
            // change color
            NSRange range=[currentString rangeOfString:word];
            [string addAttribute:NSForegroundColorAttributeName value:[UIColor redColor] range:range];
        }
    }

    // assign new color to textView's text
    [self.textView setAttributedText:string];
}
KarlHarnois
  • 115
  • 7

2 Answers2

14

Simply save and restore the selected range:

NSRange selectedRange = self.textView.selectedRange;
self.textView.attributedText = string;
self.textView.selectedRange = selectedRange;
rmaddy
  • 314,917
  • 42
  • 532
  • 579
  • 1
    That doesn't work if you have string longer than textField can display and move cursor to the beginning. When you type text, cursor stays in one position. – vahotm May 10 '18 at 15:01
0

Best way is to temporary disable delegate, I also tried with cursor save and restore but that made problems when there is custom changing on shouldChangeTextIn... on the end disabling delegate resolved all problems:

Objective C:

id<UITextViewDelegate> tempDelegate = textView.delegate;
// Do your text changes
textView.delegate = tempDelegate;

Swift:

let tempDelegate = self.textView.delegate
// Do your text changes
self.textView.delegate = tempDelegate
omanosoft
  • 4,239
  • 1
  • 9
  • 16