Resizing UILabel to fit with Word Wrap

Here is the most elegant (yet somewhat hackish) way I found to make this work:

  1. Split the string into words
  2. Calculate the width of each word using the current font size
  3. Reduce the size of the string until each the word fits into one line

Resource consumption is low enough for this to work even in UITableViews full of strings edited this way.

Here is the new code:

//Set the text  
self.textLabel.text = text;
//Largest size used  
NSInteger fsize = 200;  textLabel.font = [UIFont fontWithName:@"Verdana-Bold"
                                                         size:fsize];

//Calculate size of the rendered string with the current parameters
float height = 
      [text sizeWithFont:textLabel.font
       constrainedToSize:CGSizeMake(textLabel.bounds.size.width,99999) 
           lineBreakMode:UILineBreakModeWordWrap].height;

//Reduce font size by 5 while too large, break if no height (empty string)
while (height > textLabel.bounds.size.height and height != 0) {   
    fsize -= 5;  
    textLabel.font = [UIFont fontWithName:@"Verdana-Bold" size:fsize];   
    height = [text sizeWithFont:textLabel.font 
              constrainedToSize:CGSizeMake(textLabel.bounds.size.width,99999) 
                  lineBreakMode:UILineBreakModeWordWrap].height;
};

// Loop through words in string and resize to fit
for (NSString *word in [text componentsSeparatedByString:@" "]) {
    float width = [word sizeWithFont:textLabel.font].width;
    while (width > textLabel.bounds.size.width and width != 0) {
        fsize -= 3;
        textLabel.font = [UIFont fontWithName:@"Verdana-Bold" size:fsize];
        width = [word sizeWithFont:textLabel.font].width;

    }
}

Here's my version of 0x90's answer in a category:

@implementation UILabel (MultilineAutosize)

- (void)adjustFontSizeToFit
{
    //Largest size used
    NSInteger fsize = self.font.pointSize;

    //Calculate size of the rendered string with the current parameters
    float height = [self.text sizeWithFont:self.font
                         constrainedToSize:CGSizeMake(self.bounds.size.width, MAXFLOAT)
                             lineBreakMode:NSLineBreakByWordWrapping].height;

    //Reduce font size by 5 while too large, break if no height (empty string)
    while (height > self.bounds.size.height && height > 0) {
        fsize -= 5;
        self.font = [self.font fontWithSize:fsize];
        height = [self.text sizeWithFont:self.font
                       constrainedToSize:CGSizeMake(self.bounds.size.width, MAXFLOAT)
                           lineBreakMode:NSLineBreakByWordWrapping].height;
    };

    // Loop through words in string and resize to fit
    for (NSString *word in [self.text componentsSeparatedByString:@" "]) {
        float width = [word sizeWithFont:self.font].width;
        while (width > self.bounds.size.width && width > 0) {
            fsize -= 3;
            self.font = [self.font fontWithSize:fsize];
            width = [word sizeWithFont:self.font].width;
        }
    }
}

@end

You can use the code above in a Category for UILabel

UILabel+AdjustFontSize.h

@interface UILabel (UILabel_AdjustFontSize)

- (void) adjustsFontSizeToFitWidthWithMultipleLinesFromFontWithName:(NSString*)fontName size:(NSInteger)fsize andDescreasingFontBy:(NSInteger)dSize;

@end

UILabel+AdjustFontSize.m

@implementation UILabel (UILabel_AdjustFontSize)

- (void) adjustsFontSizeToFitWidthWithMultipleLinesFromFontWithName:(NSString*)fontName size:(NSInteger)fsize andDescreasingFontBy:(NSInteger)dSize{

    //Largest size used  
    self.font = [UIFont fontWithName:fontName size:fsize];

    //Calculate size of the rendered string with the current parameters
    float height = [self.text sizeWithFont:self.font
                    constrainedToSize:CGSizeMake(self.bounds.size.width,99999) 
                        lineBreakMode:UILineBreakModeWordWrap].height;

    //Reduce font size by dSize while too large, break if no height (empty string)
    while (height > self.bounds.size.height && height != 0) {   
        fsize -= dSize;
        self.font = [UIFont fontWithName:fontName size:fsize];   
        height = [self.text sizeWithFont:self.font 
                  constrainedToSize:CGSizeMake(self.bounds.size.width,99999) 
                      lineBreakMode:UILineBreakModeWordWrap].height;
    };

    // Loop through words in string and resize to fit
    for (NSString *word in [self.text componentsSeparatedByString:@" "]) {
        float width = [word sizeWithFont:self.font].width;
        while (width > self.bounds.size.width && width != 0) {
            fsize -= dSize;
            self.font = [UIFont fontWithName:fontName size:fsize];
            width = [word sizeWithFont:self.font].width;            
        }
    }
}

@end