Handling UIContentSizeCategoryDidChangeNotification for NSAttributedString in UITextView
Asked Answered
T

1

14

I have an NSAttributedString in a UITextView and would like to handle the UIContentSizeCategoryDidChangeNotification when working with Dynamic Type and specifically the text styles. All the examples I've seen (IntroToTextKitDemo) address the case where the font is the same for the whole UI element. Does anyone know how to handle this properly so all the attributes update properly?

Note: I asked this on the developer forums when iOS 7 was under NDA. I'm posting it here because I found a solution and thought others might find it useful.

Toupee answered 21/9, 2013 at 3:34 Comment(0)
T
10

I found a solution. When handling the notification you need to walk the attributes and look for the text styles and update the font:

- (void)preferredContentSizeChanged:(NSNotification *)aNotification
{
    UITextView *textView = <the text view holding your attributed text>

    NSMutableAttributedString *attributedString = [[NSMutableAttributedString alloc] initWithAttributedString:textView.attributedText];
    NSRange range = NSMakeRange(0, attributedString.length - 1);

    // Walk the string's attributes
    [attributedString enumerateAttributesInRange:range options:NSAttributedStringEnumerationReverse usingBlock:
     ^(NSDictionary *attributes, NSRange range, BOOL *stop) {

         // Find the font descriptor which is based on the old font size change
         NSMutableDictionary *mutableAttributes = [NSMutableDictionary dictionaryWithDictionary:attributes];
         UIFont *font = mutableAttributes[@"NSFont"];
         UIFontDescriptor *fontDescriptor = font.fontDescriptor;

         // Get the text style and get a new font descriptor based on the style and update font size
         id styleAttribute = [fontDescriptor objectForKey:UIFontDescriptorTextStyleAttribute];
         UIFontDescriptor *newFontDescriptor = [UIFontDescriptor preferredFontDescriptorWithTextStyle:styleAttribute];

         // Get the new font from the new font descriptor and update the font attribute over the range
         UIFont *newFont = [UIFont fontWithDescriptor:newFontDescriptor size:0.0];
         [attributedString addAttribute:NSFontAttributeName value:newFont range:range];
     }];

    textView.attributedText = attributedString;
}
Toupee answered 21/9, 2013 at 3:34 Comment(1)
Thanks, very handy. 3rd line of the method should be NSRange range = NSMakeRange(0, attributedString.length); to cover the entire text.Berkie

© 2022 - 2024 — McMap. All rights reserved.