Calculating number of lines of dynamic UILabel (iOS7)

25,351

Solution 1

Use suggested in documentation method :

- (CGRect)boundingRectWithSize:(CGSize)size options:(NSStringDrawingOptions)options attributes:(NSDictionary *)attributes context:(NSStringDrawingContext *)context NS_AVAILABLE_IOS(7_0);

E.g.

    CGSize maxSize = CGSizeMake(self.label.frame.size.width, MAXFLOAT);

    CGRect labelRect = [self.label.text boundingRectWithSize:maxSize options:NSStringDrawingUsesLineFragmentOrigin attributes:@{NSFontAttributeName:self.label.font} context:nil];

    NSLog(@"size %@", NSStringFromCGSize(labelRect.size));

Solution 2

I was having trouble using boundingRectWithSize directly on my UILabel's attributedText — it was not accounting for the wrap to multiple lines, (the returned height was always 17.5). To work around this, I had to use boundingRectWithSize on the UILabel's text property and pass in the attributes dictionary separately (and not via [self.myLabel.attributedText attributesAtIndex:0 effectiveRange:nil]).

CGRect labelSize = CGRectIntegral([self.myLabel.text     
    boundingRectWithSize:CGSizeMake(self.myLabel.frame.size.width, MAXFLOAT) 
    options:NSStringDrawingUsesLineFragmentOrigin|NSStringDrawingUsesFontLeading
    attributes:@{NSFontAttributeName:self.myLabel.font, 
    NSParagraphStyleAttributeName:paragraphStyle} context:nil]);

Solution 3

You can use this simple method:

which will return number of lines

- (int)lineCountForLabel:(UILabel *)label
{
    CGFloat labelWidth = label.frame.size.width;
    int lineCount = 0;
    CGSize textSize = CGSizeMake(labelWidth, MAXFLOAT);
    long rHeight = lroundf([label sizeThatFits:textSize].height);
    long charSize = lroundf(label.font.leading);
    lineCount = (int)( rHeight / charSize );
    return lineCount;
}

by calling

[self lineCountForLabel:YOUR_LABEL];
Share:
25,351
Jacek Kwiecień
Author by

Jacek Kwiecień

Never be the biggest fish in the tank

Updated on July 09, 2022

Comments

  • Jacek Kwiecień
    Jacek Kwiecień almost 2 years

    There are many solutions to this questions arround but couldn't find non-deprecated one.

    I have an UILabel with mode WordWrap and fixed width of, let's say 250. Lines are set to 0.

    Here is what I tried:

    UILabel *contentLabel = (UILabel*)[contentView viewWithTag:10];
    CGSize size = [contentLabel.text sizeWithFont:contentLabel.font forWidth:contentLabel.frame.size.width lineBreakMode:NSLineBreakByWordWrapping];
    NSLog(@"Label's height is: %d", size.height);
    

    The output of height param is always 20 (so it's like one line), while te text is like 30 lines long.

    I need that for UIScrollView purposes.

  • ninja_iOS
    ninja_iOS almost 11 years
    UILineBreakModeWordWrap is deprecrecated use NSLineBreakByWordWrapping
  • Mr. T
    Mr. T almost 11 years
    In iOS 7, sizeWithFont:... is deprecated as well. Use boundingRectWithSize:... instead.
  • botbot
    botbot over 10 years
    sizeWithFont is deprecate. OP wanted non-deprecated solution.
  • Siddh
    Siddh over 10 years
    In iOS 7,you can use boundingRectWithSize: instead sizeWithFont:.
  • Rick van der Linde
    Rick van der Linde about 10 years
    Don't forget to ceil the width and height; ceil(labelRect.size.width);
  • Bagusflyer
    Bagusflyer almost 10 years
    But this one only return the height of one line. How does it work for multiple lines?
  • AlexD
    AlexD over 9 years
    @bagusflyer see my answer for how I worked around the single line height result
  • Vladimír Slavík
    Vladimír Slavík over 9 years
    What if I am using autolayout and the self.myLabel.frame is not yet calculated?
  • Jacob
    Jacob about 9 years
    How can you find the number of lines from this??
  • Rifinio
    Rifinio almost 9 years
    this is working , but in order to calculate the height of multiple lines add : [label sizeToFit];
  • Lukas1
    Lukas1 almost 9 years
    I believe this post is relevant to the question, although it doesn't answer it
  • Lukas1
    Lukas1 almost 9 years
    @VladimírSlavík you should call this code only when frame is already known; Can't do it any other way I'm afraid. Call this functionality at appropriate time, such as viewDidLoad etc
  • CIFilter
    CIFilter over 7 years
    This is so stupid. I've been fussing with this exact problem for hours. Why on earth wouldn't the existing attributes work?