12

If the sizeWithFont:constrainedToSize:lineBreakMode: method is deprecated in iOS7, how can I automatically resize a UILabel to dynamically adjust its height and width to fit the text?

Tim
  • 8,932
  • 4
  • 43
  • 64
luca
  • 36,606
  • 27
  • 86
  • 125
  • 1
    Definitely interested to found out this. I tried using boundingRect instead, but you can't enter the constraints like you can with the above. – Tim Sep 07 '13 at 11:20
  • what's wrong with boundingRectWithSize:options:attributes:context? – peko Sep 09 '13 at 13:16
  • I must have been misusing it, I will give it another go! – Tim Sep 10 '13 at 09:02
  • Still can't seem to get it working, when I update the frame of the IBOutlet UILabel, nothing changes at all on the screen, despite the two frames being different. – Tim Sep 15 '13 at 15:18
  • This will not work "as is" with auto-layout. Check my solution here: http://stackoverflow.com/a/18933978/557054 – Deniss Fedotovs Sep 21 '13 at 15:56

2 Answers2

8

I ended up using this. Works for me. This does not work with IBOutlets object but useful when computing dynamically the height of the text on uitableview's heightForRowAtIndexPath: method.

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;
John Paul Manoza
  • 1,735
  • 25
  • 22
6

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
  • 1
    This is a life saver! The amount of time I have spent messing around with this is unreal for such as simple problem I'm trying to solve. – Dominic Williams Mar 02 '14 at 12:49
  • I'm using this, and it resizes the label well, but when the label is re-added to the superview the position is wrong, even though I can verify that the origin is still set correctly on the frame – Pete Martin Mar 04 '14 at 13:50
  • @PeteMartin are you sure one of superviews is not UITableViewCell or other cached UI element? In that case some workaround is needed. – Deniss Fedotovs Mar 06 '14 at 12:33
  • @DenissFedotovs Yes, it sits in a UITableViewCell up the hierarchy. Do you happen to know of the workaround? – Pete Martin Mar 08 '14 at 14:55
  • @PeteMartin Inside your tableView:cellForRowAtIndexPath: function create temporary identical duplicateLabel (same width, font and text) on self.view, resize height by using code above, make same height for your label inside UITableViewCell frame, remove duplicateLabel from self.view. Should do the trick. – Deniss Fedotovs Mar 10 '14 at 21:44