NSAttributedString reporting incorrect sizes for UITextView sizeThatFits and boundingRectWithSize with correct options set

后端 未结 3 845
不思量自难忘°
不思量自难忘° 2021-02-15 00:26

I have an NSAttributedString that is reporting a boundingRectWithSize (and by extension a UITextView which improperly calculates its sizeThatFits) when the font size is decrease

3条回答
  •  无人及你
    2021-02-15 00:40

    I ended up fixing this but found a lack of information on the web about it, so I decided to document my solution here.

    NSOriginalFont attributes are created when the font used doesn't support one or more characters in the string. NSAttributedString adds these attributes that track what the font was "supposed" to be before a substitution to Helvetica occurred. I could make up a situation where this is useful (an all-caps font that you sometimes run uppercaseString: on?) but it wasn't useful to me.

    In fact it was harmful. As I iterated through my font related attributes to decrease the size as shown above the visible size of the text was decreasing but the NSOriginalFont attribute retained a reference to the large size.

    There's no built in constant for NSOriginalFont but if you call it by name it's possible to strip it from your NSMutableAttributedString. If you do you'll begin to get proper results from sizeThatFits, boundingRectWithSize, and other similar functions assuming that you're passing the correct options.

    I ended up creating a simple category method on NSMutableAttributedString, included below, that works well.

    NSMutableAttributedString+StripOriginalFont.h

    @interface NSMutableAttributedString (StripOriginalFont)
    
    - (void) stripOriginalFont;
    
    @end
    

    NSMutableAttributedString+StripOriginalFont.m

    @implementation NSMutableAttributedString (StripOriginalFont)
    
    - (void) stripOriginalFont{
        [self enumerateAttribute:@"NSOriginalFont" inRange:NSMakeRange(0, self.length) options:0 usingBlock:^(id value, NSRange range, BOOL *stop) {
            if (value){
                [self removeAttribute:@"NSOriginalFont" range:range];
            }
        }];
    }
    
    @end
    

    Presumably you could simply modify it to keep it "in-sync" instead of removing it entirely but it wasn't useful to me for this particular project.

提交回复
热议问题