NSAttributedString Font Change While Retaining Format Attributes

368 views Asked by At

I have an existing NSAttributedString that may include user edited attributes (i.e. Bold, Italic, Underline). I need to be able to change the base font from say Georgia to Helvetica, while maintaining the format attributes. Setting the font like so, overrides all format attributes (i.e. Georgia-Bold):

NSDictionary *fontFaceStyle = [[NSDictionary alloc] init];
fontFaceStyle = @{NSFontAttributeName:[UIFont fontWithName:@"Helvetica" size:12.0]};
[combinedAttributedTextString setAttributes:fontFaceStyle range:NSMakeRange(0, combinedAttributedTextString.length)];

I have seen some different but related threads that suggest enumerating over each attribute span in the string, make font change, then reapply the applicable format attributes. This seems pretty intensive, and I'm not sure how you'd apply it when multiple attributes could be present (i.e. Bold AND Italic AND Underline).

Thanks for any suggestions.

1

There are 1 answers

1
Henrik On

I had the exact same issue, and enumerating works well. Here "range" is the range you want to work on, and "newFamily" is a font-family. I am using textStorage, which I assume is doing useful cleanup for these types of edits when wrapping with calls to beginEditing() / endEditing().

textStorage.beginEditing()
textStorage.enumerateAttributes(in: range, options: [], using: { attr, attrRange, _ in
    if let font = attr[NSFontAttributeName] as? NSFont {
        let newFont = NSFontManager.shared().convert(font, toFamily: newFamily)
        storage.addAttribute(NSFontAttributeName, value: newFont, range: attrRange)
    }
})
textStorage.endEditing()