Changing attributes on a UITextView without resetting the attributedText property
Asked Answered
D

3

8

I have a UITextView that is parsed and has its attributes changed when certain characters are typed. The text is not changed, only the attributes that describe the text's formatting.

If I parse on every character entry, I'm essentially grabbing the text, creating an attributed string with the right formatting, and setting the attributedText property of the textview to my new attributed string. This totally breaks autocorrect, the double-space shortcut, and spell check.

If I parse only when certain special characters are typed, this works a little better, but I get weird bugs like the second word of every sentence is capitalized.

- (BOOL)textView:(UITextView *)textView shouldChangeTextInRange:(NSRange)range replacementText:(NSString *)text {
    if (text.length == 0) {
        return YES;
    }
    unichar firstCharacterInText = [text characterAtIndex:0];
    if (/* special character */) {
        [self processTextView];
    }
}

- (void) processTextView {
    NSString *text = self.text;

    NSMutableAttributedString *attributedString = [[NSMutableAttributedString alloc] initWithString:text];

    [attributedString addAttribute:NSFontAttributeName value:[UIFont fontWithName:kFontRegular size:12.0f] range:NSMakeRange(0, text.length)];
    [attributedString addAttribute:NSForegroundColorAttributeName value:[UIColor textColor] range:NSMakeRange(0, text.length)];
    // set other properties 
}

My question is: Is there a way to change the text attributes of my text view without resetting the textview's attributedText property and breaking all those handy features of UITextView?

Dampier answered 23/4, 2013 at 2:52 Comment(2)
Just for posterity: I had the same issue with autocorrect breaking when I was setting the attributedText in textViewDidChange/shouldChange and was about to file a radar when I realized this isn't really a bug: this behaivour is caused by the fact that the text view totally changes its contents every time a new character is inputted, so autocorrect, the double-space shortcut, etc. don't get a chance to work. I don't see a solution to this, other than exploring CoreText.Turf
With iOS 7, you can use TextKit to achieve what you want.Proportion
P
5

Highlight texts in a range without reseting attributedText (NSAttributedString) property of UITextView.

let range = NSRange(location: 100, length: 20)
let attribute = [NSAttributedString.Key.backgroundColor: UIColor.yellow]
textStorage.addAttributes(attribute, range: range)

textStorage is a property of UITextView.

Puma answered 30/5, 2022 at 6:21 Comment(1)
amazing only textStorage helped me thank you so muchTressatressia
P
4

To elaborate on fatuhoku's comment above. You can call

func setAttributes(_ attrs: [NSAttributedString.Key: Any]?, range: NSRange)

On the text view's .textStorage.

Paleozoology answered 16/12, 2020 at 18:0 Comment(1)
Awesome tip. Should be marked as the answer.Insomniac
M
0

I had the same problem and it turned out that setting attributedText property of UITextView was triggering textViewDidChange: method. So, setting attributedText property from inside textViewDidChange: method created an infinite loop.

I made a quick fix in which I would immediately return from textViewDidChange: method every other time I make a call to that method. It seems to work OK, but I still need to check some more.

Musicology answered 14/5, 2013 at 11:31 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.