I have found that a call to boundingRectWithSize
is extremely incorrect, missing an entire additional line, when called with NSFontAttributeName : [UIFont preferredFontForTextStyle:UIFontTextStyleBody]
. However, using the font [UIFont fontWithName:@"Helvetica Neue" size:17.f]
, it is just fine.
Here is test code showing the bug:
- (void)viewDidLoad {
[super viewDidLoad];
NSString *measureText = @"I'm the king of Portmanteaus ... My students slow clap";
CGSize maxSize = CGSizeMake(226.f, CGFLOAT_MAX);
UIFont *targetFont = [UIFont preferredFontForTextStyle:UIFontTextStyleBody];
CGRect stringRect = [measureText boundingRectWithSize:maxSize
options:(NSStringDrawingUsesLineFragmentOrigin | NSStringDrawingUsesFontLeading)
attributes:@{ NSFontAttributeName : targetFont }
context:nil];
UILabel *drawLabel = [[UILabel alloc] initWithFrame:stringRect];
drawLabel.font = targetFont;
[self.view addSubview:drawLabel];
drawLabel.textColor = [UIColor blackColor];
drawLabel.text = measureText;
drawLabel.numberOfLines = 0;
}
And the output:
However, if I make targetFont = [UIFont fontWithName:@"Helvetica Neue" size:17.f];
It renders properly:
In the first case, the size is {226.20200000000008, 42.281000000000006}, but in the correct second case the size is {228.64999999999998, 60.366999999999997}. Therefore, this is not a rounding issue; this is missing an entire new line.
Is it wrong to pass [UIFont preferredFontForTextStyle:UIFontTextStyleBody]
as an argument into boundingRectWithSize
?
Edit
Per the comments in the answer below, I believe there is a bug with how iOS treats three periods in connection with the proceeding word. I have added this code:
measureText = [measureText stringByReplacingOccurrencesOfString:@" ..." withString:@"…"];
and it works properly.
A label adds a little margin round the outside of the text, and you have not allowed for that.
If, instead, you use a custom UIView exactly the size of the string rect, you will see that the text fits perfectly:
Here's the code I used. In the view controller:
And here is String Drawer (a UIView subclass):
Also, if your purpose is to make a label that contains the text by sizing its height, why not let Auto Layout do its thing? This next screen shot is a UILabel, with a width constraint 226, and no height constraint. I've assigned it your font and your text, in code. As you can see, it has sized itself to accommodate all the text:
That was achieved by this code, and no more was needed: