I have recently accomplished this and found it to be very simple. Instead of using sizeWithFont:
you should use the new boundingRectWithSize:options:attributes:context
method in iOS 7.
Set up your table view cell as usual and specify the preferredFontForTextStyle:
on your text label as such:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:TableViewCellIdentifier forIndexPath:indexPath];
//set your table view cell content here
[[cell textLabel] setText:@"Lorem ipsum dolour sit amet."];
[[cell textLabel] setNumberOfLines:0];
[[cell textLabel] setLineBreakMode:NSLineBreakByWordWrapping];
[[cell textLabel] setFont:[UIFont preferredFontForTextStyle:UIFontTextStyleBody]];
return cell;
}
Then to correctly determine the size of the text label, evaluate the boundingRectWithSize:options:attributes:context
to calculate the required height.
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
//add your table view cell content here
NSString *string = @"Lorem ipsum dolor sit amet.";
NSDictionary *attributes = @{NSFontAttributeName: [UIFont preferredFontForTextStyle:UIFontTextStyleBody]};
CGRect frame = [string boundingRectWithSize:CGSizeMake(CGRectGetWidth(tableView.bounds), CGFLOAT_MAX) options:(NSStringDrawingUsesLineFragmentOrigin | NSStringDrawingUsesFontLeading) attributes:attributes context:nil];
return ceilf(CGRectGetHeight(frame);
}
You may want to subclass your table view cell also to listen for UIContentSizeCategoryDidChangeNotification
notifications at which point you can update your UI when the user changes their preferences in Settings.app
- (void)contentSizeCategoryDidChangeNotificationHandler:(NSNotification *)notification
{
[[self textLabel] setFont:[UIFont preferredFontForTextStyle:UIFontTextStyleBody]];
}
Should you require additional padding around the text label, you can define a constant value such as
static CGFloat const TableViewCellPadding = 10.0;
With this in place, you can either add a constant value to the value returned from tableView:heightForRowAtIndexPath:
return (ceilf(CGRectGetHeight(frame) + TableViewCellPadding);
Or you could inset the frame returned from boundingRectWithSize:options:attributes:context
as such:
CGRect frame = [string boundingRectWithSize:CGSizeMake(CGRectGetWidth(tableView.bounds), CGFLOAT_MAX) options:(NSStringDrawingUsesLineFragmentOrigin | NSStringDrawingUsesFontLeading) attributes:attributes context:nil];
frame = CGRectInset(frame, 0.0, TableViewCellPadding);