sizeWithFont method is deprecated. boundingRectWithSize returns an unexpected value

前端 未结 6 1352
傲寒
傲寒 2020-12-02 06:38

In iOS7, sizeWithFont is deprecated, so I am using boundingRectWithSize(which returns a CGRect value). My code:

 UIFont *fontText =         


        
相关标签:
6条回答
  • 2020-12-02 07:18

    Here is my working code snippet:

    NSMutableDictionary *dict = [NSMutableDictionary dictionaryWithDictionary:attributeDict];
    
    NSString *headline  = [dict objectForKey:@"title"];  
    UIFont *font        = [UIFont boldSystemFontOfSize:18];  
    CGRect  rect        = [headline boundingRectWithSize:CGSizeMake(300, 1000) options:NSStringDrawingUsesLineFragmentOrigin|NSStringDrawingUsesFontLeading attributes:@{NSFontAttributeName:font} context:nil];
    
    CGFloat height      = roundf(rect.size.height +4)
    

    I added 4px to the calculated height, because without these 4px, there is one line missing.

    I use this code snippet in a tableView and add the "height" to an array of NSNumbers and I get the correct cell height for the default textLabel.

    Add 4 more pixel if you want more space under the text in the textLabel.

    **** UPDATE ****

    I do not agree with the "width bug of 40px", I shout be the 4px of missing height, because 4px is the default height of a space between a letter and the bound of a single line. You can check it with a UILabel, for a fontsize of 16 you need a UILabel height of 20.

    But if your last line has no "g" or whatever in it, the measuring could be miss the 4px of height.

    I rechecked it with a little method, I get an accurate height of 20,40 or 60 for my label and a right width less than 300px.

    To support iOS6 and iOS7, you can use my method:

    - (CGFloat)heightFromString:(NSString*)text withFont:(UIFont*)font constraintToWidth:(CGFloat)width
    {
        CGRect rect;
    
        float iosVersion = [[[UIDevice currentDevice] systemVersion] floatValue];
        if (iosVersion >= 7.0) {
            rect = [text boundingRectWithSize:CGSizeMake(width, 1000) options:NSStringDrawingUsesLineFragmentOrigin|NSStringDrawingUsesFontLeading attributes:@{NSFontAttributeName:font} context:nil];
        }
        else {
            CGSize size = [text sizeWithFont:font constrainedToSize:CGSizeMake(width, 1000) lineBreakMode:NSLineBreakByWordWrapping];
            rect = CGRectMake(0, 0, size.width, size.height);
        }
        NSLog(@"%@: W: %.f, H: %.f", self, rect.size.width, rect.size.height);
        return rect.size.height;
    }
    

    **** UPGRADE ****

    Thanks to your comments, I upgraded my function as followed. Since sizeWithFont is deprecated and you will get a warning in XCode, I added the diagnostic-pragma-code to remove the warning for this particular function-call/block of code.

    - (CGFloat)heightFromStringWithFont:(UIFont*)font constraintToWidth:(CGFloat)width
    {
        CGRect rect;
    
        if ([self respondsToSelector:@selector(boundingRectWithSize:options:attributes:context:)]) {
            rect = [self boundingRectWithSize:CGSizeMake(width, 1000) options:NSStringDrawingUsesLineFragmentOrigin|NSStringDrawingUsesFontLeading attributes:@{NSFontAttributeName:font} context:nil];
        }
        else {
    #pragma GCC diagnostic push
    #pragma GCC diagnostic ignored "-Wdeprecated-declarations"
            CGSize size = [self sizeWithFont:font constrainedToSize:CGSizeMake(width, 1000) lineBreakMode:NSLineBreakByWordWrapping];
            rect = CGRectMake(0, 0, size.width, size.height);
    #pragma GCC diagnostic pop
        }
        return ceil(rect.size.height);
    }
    

    In addition to the 4px topic: depending which font and font-weight you use, the calculation returns different height-values. In my case: HelveticaNeue-Medium with a fontsize of 16.0 returns a line-height of 20.0 for a single line but 39.0 for two lines, 78px for 4 lines --> 1px missing for every line - beginning with line 2 - but you want to have your fontsize + 4px linespace for every line you have to get a height-result.
    Please keep that in mind while coding!
    I don´t have a function yet for this "problem" but I will update this post when I´m finished.

    0 讨论(0)
  • 2020-12-02 07:20

    If I understand correctly, you are using boundingRectWithSize: just as a way of getting the size you would get with sizeWithFont (meaning you want directly the CGSize, not the CGRect)?

    This looks like what you are looking for :

    Replacement for deprecated sizeWithFont: in iOS 7?

    They are using sizeWithAttributes: to get the size, as a replacement for sizeWithFont.

    Do you still get the wrong size using something like this :

    UIFont *fontText = [UIFont fontWithName:[AppHandlers zHandler].fontName size:16];
                        // you can use your font.
    
    expectedLabelSize = [myString sizeWithAttributes:@{NSFontAttributeName:fontText}];
    
    0 讨论(0)
  • 2020-12-02 07:25

    for finding size of label run time sizewithfont is deprecated for iOS 7.0 instead of that you have to use -boundingRectWithSize:options:attributes:context: method

    you can use it like below code

    CGSize constraint = CGSizeMake(MAXIMUM_WIDHT, TEMP_HEIGHT);
    NSRange range = NSMakeRange(0, [[self.message body] length]);
    
    NSDictionary *attributes = [YOUR_LABEL.attributedText attributesAtIndex:0 effectiveRange:&range];
    CGSize boundingBox = [myString boundingRectWithSize:constraint options:NSStringDrawingUsesFontLeading attributes:attributes context:nil].size;
    int numberOfLine = ceil((boundingBox.width) / YOUR_LABEL.frame.size.width);
    CGSize descSize = CGSizeMake(ceil(boundingBox.width), ceil(self.lblMessageDetail.frame.size.height*numberOfLine));
    
    CGRect frame=YOUR_LABEL.frame;
    frame.size.height=descSize.height;
    YOUR_LABEL.frame=frame;
    

    here you have to give width to maximum length for finding height or width.

    try this it is working for me.

    0 讨论(0)
  • 2020-12-02 07:26

    The @SoftDesigner's comment has worked for me

    CGRect descriptionRect = [description boundingRectWithSize:CGSizeMake(width, 0)
                                                           options:(NSStringDrawingUsesLineFragmentOrigin|NSStringDrawingUsesFontLeading)
                                                        attributes:@{NSFontAttributeName : [UIFont systemFontOfSize:12]}
                                                           context:nil];
    result = ceil(descriptionRect.size.height);
    
    0 讨论(0)
  • 2020-12-02 07:36

    How about create new label and using sizeThatFit:(CGSize)size ??

    UILabel *gettingSizeLabel = [[UILabel alloc] init];
    gettingSizeLabel.font = [UIFont fontWithName:@"YOUR FONT's NAME" size:16];
    gettingSizeLabel.text = @"YOUR LABEL's TEXT";
    gettingSizeLabel.numberOfLines = 0;
    gettingSizeLabel.lineBreakMode = NSLineBreakByWordWrapping;
    CGSize maximumLabelSize = CGSizeMake(310, CGFLOAT_MAX);
    
    CGSize expectSize = [gettingSizeLabel sizeThatFits:maximumLabelSize];
    

    Edit: This upper code is not good for ios 7 and above, so please use below:

    CGRect textRect = [myString boundingRectWithSize:maximumLabelSize   
                             options:NSStringDrawingUsesLineFragmentOrigin| NSStringDrawingUsesFontLeading
                             attributes:@{NSFontAttributeName:fontText}
                             context:nil];
    
    0 讨论(0)
  • 2020-12-02 07:42

    Maybe you need to provide additional option to the method that is suggested in this answer:

    CGSize maximumLabelSize = CGSizeMake(310, CGFLOAT_MAX);
    CGRect textRect = [myString boundingRectWithSize:maximumLabelSize   
                                             options:(NSStringDrawingUsesLineFragmentOrigin|NSStringDrawingUsesFontLeading)
                                          attributes:@{NSFontAttributeName: fontText}
                                             context:nil];
    
    0 讨论(0)
提交回复
热议问题