iOS 7 gets me a different CGSize width and height

JackoJack picture JackoJack · Sep 19, 2013 · Viewed 10.4k times · Source

I have a problem on my app on iOS 7

I calculate my label size using:

CGSize constraint = CGSizeMake(275, 141);
CGSize size;

size = [_rtLabelQuestion.plainText sizeWithFont:[UIFont fontWithName:@"KGWhattheTeacherWants" size:intFont] constrainedToSize:constraint lineBreakMode:NSLineBreakByTruncatingTail];

and then place my label frame using:

_rtLabelQuestion.frame = CGRectMake(aLabelTemp.frame.origin.x, aLabelTemp.frame.origin.y, size.width + 2 , size.height + 10);

But on iOS 7 width and height of my CGSize is always smaller from exactly intFont pixels, i've been working on that 2 days and no solution, please help, thank you !

Answer

ipmcc picture ipmcc · Sep 19, 2013

The size: you pass in to -[UIFont fontWithName:size:] is the point size of the font.

The size you get back from -[NSString sizeWithFont:constrainedToSize:lineBreakMode:] is the actual size of the laid out glyphs from the string.

If you want a given string to be a specific size, in a specific face, you will probably have to do a Newton's-method type iteration where you change the point size you're passing in until the laid out size is close enough to what you want. (I would not expect such an operation to be fast in the general case, BTW.) It might look something like this:

NSString* theString = @"FOOBAR";
CGSize constraint = CGSizeMake(275, 12);
CGFloat desiredHeight = 12.0;
CGFloat pointSize = desiredHeight;
CGFloat actualHeight = 0;
do {
    CGSize size = [theString sizeWithFont: [UIFont fontWithName:@"Helvetica" size: pointSize] constrainedToSize: constraint lineBreakMode:NSLineBreakByTruncatingTail];
    actualHeight = size.height;
    CGFloat ratio = actualHeight / desiredHeight;
    pointSize = pointSize / ratio;
} while (fabs(actualHeight - desiredHeight) > 0.01);

PS: -[NSString sizeWithFont:constrainedToSize:lineBreakMode:] is deprecated in iOS7. Compiler tells me to use -boundingRectWithSize:options:attributes:context:] instead. Using the new recommended method, it might look like this:

NSString* theString = @"FOOBAR";
CGSize constraint = CGSizeMake(275, 12);
CGFloat desiredHeight = 12.0;
CGFloat pointSize = desiredHeight;
CGFloat actualHeight = 0;
NSStringDrawingContext* ctx = [[NSStringDrawingContext alloc] init];
do {
    CGRect br = [theString boundingRectWithSize: constraint options: 0 attributes: @{ NSFontAttributeName : [UIFont fontWithName:@"Helvetica" size: pointSize] } context:ctx];
    actualHeight = br.size.height;
    CGFloat ratio = actualHeight / desiredHeight;
    pointSize = pointSize / ratio;
} while (fabs(actualHeight - desiredHeight) > 0.01);