Ruben Martinez Jr. Ruben Martinez Jr. - 1 year ago 141
Swift Question

Change UITextView Font w/o Removing Bold/Underline/Italics Formatting

I have a UITextView in an iOS app, and I want to allow the user to bold/italicize/underline/etc at will, so I gave set the allowsEditingTextAttributes property to true on the text view. However, I would also like to allow the user to change things like font and color. Currently, it seems that changing even the color property of the UITextView resets the formatting of the UITextView (i.e. gets rid of the bolding/italics/etc). Is there any way to change this without resetting the formatting? For reference, I am currently doing this to change the color:

self.textView.textColor = colorTheUserPicked //a UIColor picked by the user

EDIT: Actually, this was my bad, I was also resetting the value of the text property itself when I changed the color. Removing that allowed me to change the color as desired. However, I still can't change the font or even the font size without removing the bold/italics/etc. I realize this might be impossible, though...

Answer Source

I'll answer with an Objective-C solution since I don't code in Swift, but it should be translated easily into Swift.

NSAttributedString "effects" are stored in a NSDictionary. So it's a Key:Value system (with unicity of Key).
Bold/Italic (from your example) are inside the NSFontAttributedName's value. That's why you can't set it again like this.

The main key is to use enumerateAttributesInRange:options:usingBlock::

[attr enumerateAttributesInRange:NSMakeRange(0, [attr length])
                      usingBlock:^(NSDictionary *attributes, NSRange range, BOOL *stop)
     NSMutableDictionary *newAttributes = [attributes mutableCopy];
    //Do changes
    [attr addAttributes:newAttributes range:range]; //Apply effects

The following lines are at "//Do changes" place. So, if you want to change the Font size:

if ([newAttributes objectForKey:NSFontAttributeName])
    UIFont *currentFont = (UIFont *)[attributes objectForKey:NSFontAttributeName];
    UIFont *newFont = [UIFont fontWithName:[currentFont fontName] size:[currentFont pointSize]*0.5];//Here, I multiplied the previous size with 0.5
    [newAttributes setValue:newFont forKey:NSFontAttributeName];

If you want to bold/italic, etc. the font you may be interested in UIFontDescriptor, and a related question.

It shows you how to get the previous font and change get a new font with some commons with the previous one.

If you want to change the color:

if ([newAttributes objectForKey:NSForegroundColorAttributeName])//In case if there is some part of the text without color that you don't want to override, or some custom- things
     UIColor *newColor = [UIColor blueColor];
    [newAttributes setValue:newColor forKey:NSForegroundColorAttributeName];

The underline effect is in NSUnderlineStyleAttributeName's value. So analogic changes can be done.

Recommended from our users: Dynamic Network Monitoring from WhatsUp Gold from IPSwitch. Free Download