What is -[NSString sizeWithFont:forWidth:lineBreakMode:] good for?

In my question "How do I get -[NSString sizeWithFont:forWidth:lineBreakMode:] to work?", I learned that -[NSString sizeWithFont:constrainedToSize:lineBreakMode:] was actually what I needed.

The documentation for -[NSString sizeWithFont:forWidth:lineBreakMode:] states explains it doesn't actually wrap the text to additional lines. So how would I use it? (Examples would help.)


It works great for multi line strings as well.

Basically its a function that lets you see how big a string is going to be when rendered with a font and line break mode.

I use it in a few spots in my application when I have variable length text I want to display in a certain area.

By default a UILabel will center the text vertically. To have the text top aligned you need to size the label to be only the height required by the string that's in it.

I use this method to do this.

And example of how I would use it to do that is as follows:

//Calculate the expected size based on the font and linebreak mode of your label
CGSize maximumLabelSize = CGSizeMake(296,9999);

CGSize expectedLabelSize = [yourString sizeWithFont:yourLabel.font 
                        constrainedToSize:maximumLabelSize 
                        lineBreakMode:yourLabel.lineBreakMode]; 

//adjust the label the the new height.
CGRect newFrame = yourLabel.frame;
newFrame.size.height = expectedLabelSize.height;
yourLabel.frame = newFrame;

You specify how big of an area you have to put the text in, and then this method tells you how much space it will take up (wrapping as required). Also if the string will overflow the bounds of the rect you provide you can tell and then decided how to display the text.

The reference to it not actually wrapping the text is there because this method doesn't actually do anything to the text. It just virtually lays it out and returns how big of an area it would need to really lay it out.

its the responsibility of the label (or what ever container you are using for the text) to perform the wrapping/what ever else that needs to be done.

Hope that helps.

chris.


For a while I thought this routine was simply broken. It sounds like it's the perfect routine for working out how high a piece of text is, when wrapped at a certain width. However this is not what it does. Indeed, the height returned is always a single line. (Which is pointless, incidentally: UIFont's -leading returns the same value.)

To quote the documentation at the time of writing:

Although it computes where line breaks would occur, this method does not actually wrap the text to additional lines; [...]

This sentence confused me for a long time. My thoughts ran along the lines of:

  • Computing line-breaks, but not wrapping. Eh?
  • Maybe they mean the receiving NSString itself won't be mutated to reflect line-breaks? But I don't expect that anyway?
  • This sentence is not consistent with itself. I have no choice but to ignore it.

However, it turns out there's a meaning that matches the behaviour we see. It seems that what they mean is:

This routine will compute where the first line-break will occur, and all text after this is ignored for the purposes of calculating the bounding box.

The bounding box returned will therefore have the height of a single line and a width up to the maximum specified. (The width may be less depending on where the line-break is calculated, or if the text is short enough that it does not need the maximum width.)

To, um, answer the actual question: What is it good for? I haven't found anything useful myself: only things where I thought it would be useful, but wasn't. Some things which spring to mind, however, are:

  • Centering a single-line piece of text. I'm thinking buttons and/or titles here. (Although UILabel and UIButton can do it, sometimes you want to draw it yourself.)
  • Calculating the bounds for an "extract" of a longer piece of text. Here I'm thinking about where you might want to show a snippet of a much larger piece of text.

It sounds like it would be good for single line labels. For example, if you're drawing a string that may be truncated or have a line break, but you won't actually draw more than one line. It could still be helpful to know the exact height and width of the string, so you can position it exactly where you want it (and draw other UI items around it).