Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

UIKit's [NSString sizeWithFont:constrainedToSize:] in AppKit

Is there any equivalent method in AppKit (for Cocoa on Mac OS X) that does the same thing as UIKit's [NSString sizeWithFont:constrainedToSize:]?

If not, how could I go about getting the amount of space needed to render a particular string constrained to a width/height?

Update: Below is a snippet of code I'm using that I expect would produce the results I'm after.

NSDictionary *attributes = [NSDictionary dictionaryWithObjectsAndKeys:
                            [NSFont systemFontOfSize: [NSFont smallSystemFontSize]], NSFontAttributeName,
                            [NSParagraphStyle defaultParagraphStyle], NSParagraphStyleAttributeName,
                            nil];
NSSize size = NSMakeSize(200.0, MAXFLOAT);
NSRect bounds;

bounds = [@"This is a really really really really really really really long string that won't fit on one line"
             boundingRectWithSize: size
             options: NSStringDrawingUsesFontLeading
             attributes: attributes];

NSLog(@"height: %02f, width: %02f", bounds.size.height, bounds.size.width);

I would expect that the output width would be 200 and the height would be something greater than the height of a single line, however it produces:

height: 14.000000, width: 466.619141

Thanks!

like image 505
Bryan Kyle Avatar asked Feb 17 '11 19:02

Bryan Kyle


4 Answers

Try this one:

bounds = [value boundingRectWithSize:size options:NSLineBreakByWordWrapping | NSStringDrawingUsesLineFragmentOrigin attributes:attributes];
like image 55
vvkatwss vvkatwss Avatar answered Nov 17 '22 13:11

vvkatwss vvkatwss


The newer NSExtendedStringDrawing category API (methods with the NSStringDrawingOptions argument) behaves in the single line mode. If you want to measure/render in multi line mode, want to specify NSStringDrawingUsesLineFragmentOrigin.

like image 24
Aki Avatar answered Nov 17 '22 14:11

Aki


EDIT: You should be able to do things the normal way in Lion and later. The problems described below have been fixed.


There is no way to accurately measure text among the current Mac OS X APIs.

There are several APIs that promise to work but don't. That's one of them; Core Text's function for this purpose is another. Some methods return results that are close but wrong; some return results that seem to mean nothing at all. I haven't filed any bugs on these yet, but when I do, I'll edit the Radar numbers into this answer. You should file a bug as well, and include your code in a small sample project.

[Apparently I have already filed the Core Text one: 8666756. It's closed as a duplicate of an unspecified other bug. For Cocoa, I filed 9022238 about the method Dave suggested, and will file two NSLayoutManager bugs tomorrow.]

This is the closest solution I've found.

like image 27
Peter Hosey Avatar answered Nov 17 '22 13:11

Peter Hosey


If you want to constrain the string to a certain size, you use -[NSString boundingRectWithSize:options:attributes:]. The .size of the returned NSRect is the size you're looking for.

like image 1
Dave DeLong Avatar answered Nov 17 '22 14:11

Dave DeLong