6

I have a UILabel with adjustsFontSizeToFitWidth set to YES and as expected it shrinks the font displayed on screen when the text is too large to be drawn at the size of the font property.

I have already interrogated the font property but this remains the same as it was when originally set on the label, and UILabel doesn't seem to have any other properties that could be of use.

Is there a way to find out what the size of the shrunken text drawn by the label is?

EDIT: Not a duplicate as suggested because sizeWithFont:minFontSize:actualFontSize:forWidth:lineBreakMode: was deprecated in iOS7

Stephen Groom
  • 3,887
  • 1
  • 15
  • 23
  • 1
    Possible duplicate of [How to figure out the font size of a UILabel when -adjustsFontSizeToFitWidth is set to YES?](http://stackoverflow.com/questions/2396715/how-to-figure-out-the-font-size-of-a-uilabel-when-adjustsfontsizetofitwidth-is) – Steve Wilford Oct 07 '15 at 10:31
  • The answer in that question is deprecated with the message "There is no exact alternative for this method. Human interface guidelines discourage changing the font size this way because it leads to an inconsistent user experience. See UILabel as a possible alternative for some use cases." – Stephen Groom Oct 07 '15 at 10:39
  • 1
    Check the [linked issue](http://stackoverflow.com/a/19200337/2613662) in the [comment](http://stackoverflow.com/questions/2396715/how-to-figure-out-the-font-size-of-a-uilabel-when-adjustsfontsizetofitwidth-is#comment28402916_2397244) on that answer – Steve Wilford Oct 07 '15 at 10:40

2 Answers2

15

Turns out it is a bit more complex since iOS 7 deprecated the useful sizeWithFont:minFontSize:actualFontSize:forWidth:lineBreakMode:, as used in the suggested duplicate.

We now have to use NSAttributedString instead.

Create an NSAttributedString from the string to be / that is set on the label. Setting the entire attributed string's font to whatever the label's font is.

NSDictionary *attributes = @{NSFontAttributeName : self.label.font};
NSAttributedString *attributedString = [[NSAttributedString alloc] initWithString:text
                                                                       attributes:attributes];

Then, create a NSStringDrawingContext object, configured to use the minimum scale factor of the label. This will be used to assist in the calculation of the actual font size.

NSStringDrawingContext *context = [[NSStringDrawingContext alloc] init];
context.minimumScaleFactor = self.label.minimumScaleFactor;

We can then use the NSAttributedString method to calculate the bounding rect, and further configure the NSStringDrawingContext:

[attributedString boundingRectWithSize:self.label.bounds.size
                               options:NSStringDrawingUsesLineFragmentOrigin
                               context:context];

This will make a drawing pass and the context will be updated to include the scale factor that was used in order to draw the text in the space available (the label's size).

Getting the actual font size is then as simple as:

CGFloat actualFontSize = self.label.font.pointSize * context.actualScaleFactor;
Community
  • 1
  • 1
Steve Wilford
  • 8,894
  • 5
  • 42
  • 66
  • 1
    I've translated your answer into Swift for use in my project. When I get the CGRect by using boundingRectWithSize, I can see that it is indeed a wider CGRect when the text is longer. What I don't see is the value of context changing. I've asked this question (with the Swift code) here: http://stackoverflow.com/questions/34622503/when-do-adjustsfontsizetofitwidth-or-boundingrectwithsize-change-the-context-act – RanLearns Jan 05 '16 at 23:50
0

I've answered your question inside this link for the Swift 5 that is similar to your question

However, we can get actualFontSize as follows: For one-line UILabel

extension UILabel {

     var actualFontSize: CGFloat {
    //initial label
     let fullSizeLabel = UILabel()
     fullSizeLabel.font = self.font
     fullSizeLabel.text = self.text
     fullSizeLabel.sizeToFit()

     var actualFontSize: CGFloat = self.font.pointSize * (self.bounds.size.width / fullSizeLabel.bounds.size.width);

    //correct, if new font size bigger than initial
actualFontSize = actualFontSize < self.font.pointSize ? actualFontSize : self.font.pointSize;

     return actualFontSize
    }

}

Getting the actual font size is then as simple as:

let currentLabelFontSize = myLabel.actualFontSize
Merichle
  • 693
  • 11
  • 15