11

I have an NSString, and I want to know its height to create an appropriate UILabel.

Doing this

NSString *string = @"this is an example"; 
CGSize size = [string sizeWithFont:[UIFont systemFontOfSize:10.0f] 
                          forWidth:353.0 
                     lineBreakMode:UILineBreakModeWordWrap];
float height = size.height;

height is now 13.0. If I use this string

NSString *string = @"this is an example this is an example this is an example 
                     this is an example this is an example this is an example 
                     this is an example this is an example this is an example 
                     this is an example this is an example this is an example 
                     this is an example this is an example this is an example 
                     this is an example "; 

height is always 13.0 (and with 353 as width, that's impossible)... what am I doing wrong?

ADD:

size.width;

works fine... so it's like if the lineBreakMode is not correct... but it is, isn't it?

Alex Cio
  • 6,014
  • 5
  • 44
  • 74
JAA
  • 1,024
  • 3
  • 20
  • 34
  • You're taking that size from the string object, not the CGSize you just created. Is that a typo? – Matt Wilding Aug 05 '11 at 21:08
  • but `sizeWithFont:forWidth:lineBreakMode` takes an NSString (not a UILabel, for example)... so it's correct... or not? – JAA Aug 05 '11 at 21:10
  • It doesn't take it, per say, it acts on it, and gives you back a size. So if you were to change `float height = string.height;` to `float height = size.height;`, I'm guessing it'll make more sense. – Matt Wilding Aug 05 '11 at 21:12
  • yes yes, sorry... I wrote here wrong (but in Xcode it was correct... and the log is 13.0)! – JAA Aug 05 '11 at 21:14

2 Answers2

21

The reason what you're doing doesn't work as you would expect is because

– sizeWithFont:forWidth:lineBreakMode: 

is for "Computing Metrics for a Single Line of Text" whereas

-sizeWithFont:constrainedToSize:lineBreakMode:

is for "Computing Metrics for Multiple Lines of Text". From the documentation:

Computing Metrics for a Single Line of Text

– sizeWithFont:
– sizeWithFont:forWidth:lineBreakMode:
– sizeWithFont:minFontSize:actualFontSize:forWidth:lineBreakMode:

Computing Metrics for Multiple Lines of Text

– sizeWithFont:constrainedToSize:
– sizeWithFont:constrainedToSize:lineBreakMode:

Try using -sizeWithFont:constrainedToSize:lineBreakMode: instead, e.g. this is what I usually do:

CGSize maximumLabelSize = CGSizeMake(353,9999);

CGSize expectedLabelSize = [string sizeWithFont:label.font                        
                              constrainedToSize:maximumLabelSize 
                                  lineBreakMode:label.lineBreakMode]; 

CGRect newFrame = label.frame;
newFrame.size.height = expectedLabelSize.height;
label.frame = newFrame;
PengOne
  • 48,188
  • 17
  • 130
  • 149
  • sorry, I wrote here wrong (now I've correct)! Of course, in Xcode it was right (and the log is 13.0) – JAA Aug 05 '11 at 21:14
  • That's just too much code for something that can be done with a single method. And I get a downvote, lol. – Filip Radelic Aug 05 '11 at 21:53
  • @fichek: I completely agree that your method solves the overall problem, but your answer doesn't explain why the OP's attempt failed. I use the method above to keep my label from getting too large, a problem that `-sizeToFit` cannot solve. I don't know why you were down voted. – PengOne Aug 05 '11 at 22:02
  • Everything can be solved :) `if (label.frame.size.height > maxHeight) label.frame = CGRectMake(label.frame.origin.x, label.frame.origin.y, label.frame.size.width, maxHeight);` But there was no mention of max height in the question, so I simply offered a simpler solution. – Filip Radelic Aug 05 '11 at 22:25
1

According to the Documentation

This method returns the width and height of the string constrained to the specified width. Although it computes where line breaks would occur, this method does not actually wrap the text to additional lines. If the size of the string exceeds the given width, this method truncates the text (for layout purposes only) using the specified line break mode until it does conform to the maximum width; it then returns the size of the resulting truncated string.

You should to use -[NSString sizeWithFont:constrainedToSize:lineBreakMode:] which has similar behavior but you can uuse CGFLOAT_MAX as the height in the size passed in.

Joe
  • 56,979
  • 9
  • 128
  • 135