4

In iOS 6, I am using :

CGSize labelSize = [self.text sizeWithFont:self.font constrainedToSize:size lineBreakMode:self.lineBreakMode];
self.frame = CGRectMake(self.frame.origin.x, self.frame.origin.y , labelSize.width, self.frame.size.height);

To dynamically resize a UILabel. This does not work in iOS 7 so I tried:

NSString *text = self.text;
CGFloat width = size.width;
UIFont *font = self.font;
NSAttributedString *attributedText = [[NSAttributedString alloc] initWithString:text
                                                                 attributes:@{ NSFontAttributeName: font }];

CGRect rect = [attributedText boundingRectWithSize:(CGSize){width, CGFLOAT_MAX}
                              options:NSStringDrawingUsesDeviceMetrics
                              context:nil];
CGSize size = rect.size;

self.frame = CGRectMake(self.frame.origin.x, self.frame.origin.y , size.width, self.frame.size.height);

This is inside a category on UILabel, but this is not working also... Any ideas what I should be using?

gklka
  • 2,459
  • 1
  • 26
  • 53
user426132
  • 1,341
  • 4
  • 13
  • 28
  • What part isn't working? Is the calculated frame size wrong, or is the label size change not happening? – tarmes Sep 27 '13 at 13:24

4 Answers4

6

Try something like this (working without auto-layout) :

NSDictionary *attributesDictionary = [NSDictionary dictionaryWithObjectsAndKeys:
                                                           [UIFont fontWithName:@"FontName" size:15], NSFontAttributeName,
                                                            nil];

CGRect frame = [label.text boundingRectWithSize:CGSizeMake(263, 2000.0)
                                                     options:NSStringDrawingUsesLineFragmentOrigin
                                                  attributes:attributesDictionary
                                                     context:nil];

CGSize size = frame.size;
Jordan Montel
  • 8,227
  • 2
  • 35
  • 40
3

Without more details on why it doesn't work, my guess would be that you need to use the option NSStringDrawingUsesLineFragmentOrigin in order for it to become a drop-in replacement for the old sizeWithFont:, like this:

NSString *text = ...;
CGFloat width = ...;
UIFont *font = ...;
NSAttributedString *attributedText =
    [[NSAttributedString alloc]
        initWithString:text
        attributes:@
        {
            NSFontAttributeName: font
        }];
CGRect rect = [attributedText boundingRectWithSize:(CGSize){width, CGFLOAT_MAX}
                                           options:NSStringDrawingUsesLineFragmentOrigin
                                           context:nil];
CGSize size = rect.size;

Please note the documentation mentions:

In iOS 7 and later, this method returns fractional sizes (in the size component of the returned CGRect); to use a returned size to size views, you must use raise its value to the nearest higher integer using the ceil function.

So to pull out the calculated height or width to be used for sizing views, I would use:

CGFloat height = ceilf(size.height);
CGFloat width  = ceilf(size.width);
Mr. T
  • 12,795
  • 5
  • 39
  • 47
  • @user426132 help me understand what isn't working. What part isn't behaving the way `sizeWithFont:` used to? – Mr. T Sep 30 '13 at 07:54
3
- (void)resizeLabelByContent:(UILabel *)label
{

    CGSize maxSize = CGSizeMake(label.width, 999);

    NSString *contentStr = label.text;

    UIFont *contentFont = label.font;

    CGRect contentFrame;

    NSString *version = [[UIDevice currentDevice] systemVersion];

    if ([version floatValue] < 7.0) {

        CGSize contentStringSize = [contentStr sizeWithFont:contentFont constrainedToSize:maxSize lineBreakMode:label.lineBreakMode];

        contentFrame = CGRectMake(label.left, label.top, label.width, contentStringSize.height);

    } else {

        NSDictionary *contentDic = [NSDictionary dictionaryWithObjectsAndKeys:contentFont, NSFontAttributeName, nil];

        CGSize contentStrSize = [contentStr boundingRectWithSize:maxSize options:NSStringDrawingUsesLineFragmentOrigin attributes:contentDic context:nil].size;

        contentFrame = CGRectMake(label.left, label.top, label.width, contentStrSize.height);
    }

    label.frame = contentFrame;
}
Rich
  • 8,108
  • 5
  • 46
  • 59
code_free
  • 31
  • 4
1

This should work in iOS6 and iOS7, but will break your label constraints (you need to set them all back programatically if needed):

-(void)resizeHeightForLabel: (UILabel*)label {
    label.numberOfLines = 0;
    UIView *superview = label.superview;
    [label removeFromSuperview];
    [label removeConstraints:label.constraints];
    CGRect labelFrame = label.frame;
    if ([[[UIDevice currentDevice] systemVersion] floatValue] >= 7) {
        CGRect expectedFrame = [label.text boundingRectWithSize:CGSizeMake(label.frame.size.width, 9999)
                                                        options:NSStringDrawingUsesLineFragmentOrigin
                                                     attributes:[NSDictionary dictionaryWithObjectsAndKeys:
                                                                 label.font, NSFontAttributeName,
                                                                 nil]
                                                        context:nil];
        labelFrame.size = expectedFrame.size;
        labelFrame.size.height = ceil(labelFrame.size.height); //iOS7 is not rounding up to the nearest whole number
    } else {
#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
        labelFrame.size = [label.text sizeWithFont:label.font
                                 constrainedToSize:CGSizeMake(label.frame.size.width, 9999)
                                     lineBreakMode:label.lineBreakMode];
#pragma GCC diagnostic warning "-Wdeprecated-declarations"
    }
    label.frame = labelFrame;
    [superview addSubview:label];
}

Add this method to your viewController and use it like this:

[self resizeHeightForLabel:myLabel];
//set new constraints here if needed
Deniss Fedotovs
  • 1,384
  • 12
  • 22
  • I need to resize the width not the height ... I'll give it a go.. thx – user426132 Sep 30 '13 at 07:12
  • Try it, I think it is not so hard to modify the code to resize the width. – Deniss Fedotovs Sep 30 '13 at 08:06
  • Make sure you added label to view (using IB or programmatically) before calling this method. If you are using auto-layout and constraints, try to log out label frame width/height before and after applying this function if it has changed. If frame has changed, then you have to adjust constraints. If not, then there is some error somewhere else. Try something like `NSLog (@"width:%f, height:%f", myLabel.frame.size.width, mylabel.frame.size.height);` to log width/height. – Deniss Fedotovs Sep 30 '13 at 14:14