I wrote an earlier post about multi-line labels but I wanted something more distilled. Here are some condensed notes on how to do multi-line lables with xibs.

1. Set label to multi-line.

2. Set your UILabel struts and springs.

3. Calculate label height.

+ (CGFloat)heightForLabelWithString:(NSString *)pString andWidth:(CGFloat)pWidth
{
    CGSize labelSize = [pString sizeWithFont:[UIFont fontWithName:@"HelveticaNeue" size:14.5f] constrainedToSize:CGSizeMake(pWidth, MAXFLOAT) lineBreakMode:UILineBreakModeWordWrap];
    return labelSize.height;   
}

4. Redraw label based on height.

CGFloat bodyHeight = [CustomCell heightForLabelWithString:text.body andWidth:290];
    self.bodyLabel.frame = CGRectMake(self.bodyLabel.frame.origin.x, self.bodyLabel.frame.origin.y, self.bodyLabel.frame.size.width, bodyHeight);
    
    self.frame = CGRectMake(self.frame.origin.x, self.frame.origin.y, self.frame.size.width, self.bodyLabel.frame.origin.y + self.bodyLabel.frame.size.height + 10); 

Bring it all together in code

CustomCell.h

#import <UIKit/UIKit.h>
#import "NSString.h"

@interface CustomCell : UITableViewCell

@property (strong, nonatomic) IBOutlet UILabel *bodyLabel;

+ (NSString *)reuseIdentifier;
- (void)populate:(NSString *)text;
+ (CGFloat)heightForText:(NSString *)text;
@end

CustomCell.m

#import "CustomCell.h"
#import "UITableViewCell+Utils.h"

#define kYOrigin 10

@implementation CustomCell
@synthesize bodyLabel = _bodyLabel;

- (id)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier
{
    self = [super initWithStyle:style reuseIdentifier:reuseIdentifier];
    if (self) {
        // Initialization code
    }
    return self;
}

- (void)populate:(NSString *)text
{
    self.bodyLabel.text = text;

    CGFloat bodyHeight = [CustomCell heightForLabelWithString:text andWidth:290];
    self.bodyLabel.frame = CGRectMake(self.bodyLabel.frame.origin.x, self.bodyLabel.frame.origin.y, self.bodyLabel.frame.size.width, bodyHeight);
    
    self.frame = CGRectMake(self.frame.origin.x, self.frame.origin.y, self.frame.size.width, self.bodyLabel.frame.origin.y + self.bodyLabel.frame.size.height + 10); //10 for padding
}

+ (CGFloat)heightForText:(NSString *)text
{
    CGFloat bodyHeight = [self heightForLabelWithString:text andWidth:290];
    return kYOrigin + bodyHeight + 10;
}

+ (NSString *)reuseIdentifier 
{    
    return @"CustomCellIdentifier";
}

@end

MyViewController.m

- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
        return [CustomCell heightForText:text];
}

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
    
CustomCell *cell = (CustomCell *)[tableView dequeueReusableCellWithIdentifier:[CustomCell reuseIdentifier]];
    if (cell == nil) {
        [[NSBundle mainBundle] loadNibNamed:@"CustomCell" owner:self options:nil];
        cell = _textSectionCell;
        _textSectionCell = nil;
    }        
    
    [cell populate:@”some really long multi-line body of text ...”];
    return cell; 
}

UITableViewCell+Utils.h (category)

#import "UITableViewCell+Utils.h"

@implementation UITableViewCell (Utils)

+ (CGFloat)heightForLabelWithString:(NSString *)pString 
{
    CGSize labelSize = [pString sizeWithFont:[UIFont fontWithName:@"HelveticaNeue" size:14.5f] constrainedToSize:CGSizeMake(kDefaultLabelWidth, MAXFLOAT) lineBreakMode:UILineBreakModeWordWrap];
    return labelSize.height;
}

+ (CGFloat)heightForLabelWithString:(NSString *)pString andWidth:(CGFloat)pWidth
{
    CGSize labelSize = [pString sizeWithFont:[UIFont fontWithName:@"HelveticaNeue" size:14.5f] constrainedToSize:CGSizeMake(pWidth, MAXFLOAT) lineBreakMode:UILineBreakModeWordWrap];
    return labelSize.height;   
}
@end