I want to get the font size of some text after it's been scaled down in a UILabel or UITextField. This was possible before iOS 7.0: How to get UILabel (UITextView) auto adjusted font size?. However, sizeWithFont has been deprecated in iOS 7.0. I've tried using its replacement, sizeWithAttributes, but with no success. Is there any way to do this in iOS 7.0?
5 Answers
Here's a function I made to get the adjusted font size of a UILabel:
Swift
func getApproximateAdjustedFontSizeWithLabel(label: UILabel) -> CGFloat {
if label.adjustsFontSizeToFitWidth == true {
var currentFont: UIFont = label.font
let originalFontSize = currentFont.pointSize
var currentSize: CGSize = (label.text! as NSString).sizeWithAttributes([NSFontAttributeName: currentFont])
while currentSize.width > label.frame.size.width && currentFont.pointSize > (originalFontSize * label.minimumScaleFactor) {
currentFont = currentFont.fontWithSize(currentFont.pointSize - 1)
currentSize = (label.text! as NSString).sizeWithAttributes([NSFontAttributeName: currentFont])
}
return currentFont.pointSize
}
else {
return label.font.pointSize
}
}
Objective-C
- (CGFloat)getApproximateAdjustedFontSizeWithLabel:(UILabel *)label {
if (label.adjustsFontSizeToFitWidth) {
UIFont *currentFont = label.font;
CGFloat originalFontSize = currentFont.pointSize;
CGSize currentSize = [label.text sizeWithAttributes:@{NSFontAttributeName : currentFont}];
while (currentSize.width > label.frame.size.width && currentFont.pointSize > (originalFontSize * label.minimumScaleFactor)) {
currentFont = [currentFont fontWithSize:currentFont.pointSize - 1];
currentSize = [label.text sizeWithAttributes:@{NSFontAttributeName : currentFont}];
}
return currentFont.pointSize;
}
else {
return label.font.pointSize;
}
}

- 8,350
- 16
- 53
- 95

- 813
- 7
- 26
-
1I got infinity loop using objective c code in while block – guru Dec 02 '19 at 14:21
-
This is working only for labels with one line – Fisky Sep 25 '21 at 06:34
-
Thanks, but do you have any solution for multiline UILabel? cause this doesn't work. – Sasan Soroush Sep 09 '22 at 09:10
I really liked @WaltersGE1's answer, so I made it into an extension for UILabel to make it even more convenient to use:
extension UILabel {
/// The receiver’s font size, including any adjustment made to fit to width. (read-only)
///
/// If `adjustsFontSizeToFitWidth` is not `true`, this is just an alias for
/// `.font.pointSize`. If it is `true`, it returns the adjusted font size.
///
/// Derived from: [http://stackoverflow.com/a/28285447/5191100](http://stackoverflow.com/a/28285447/5191100)
var fontSize: CGFloat {
get {
if adjustsFontSizeToFitWidth {
var currentFont: UIFont = font
let originalFontSize = currentFont.pointSize
var currentSize: CGSize = (text! as NSString).sizeWithAttributes([NSFontAttributeName: currentFont])
while currentSize.width > frame.size.width && currentFont.pointSize > (originalFontSize * minimumScaleFactor) {
currentFont = currentFont.fontWithSize(currentFont.pointSize - 1)
currentSize = (text! as NSString).sizeWithAttributes([NSFontAttributeName: currentFont])
}
return currentFont.pointSize
}
return font.pointSize
}
}
}

- 751
- 6
- 18
-
Thanks. It works, but could/should be optimized by halving the pointSize difference each time instead of decrementing it. – WaltersGE1 Sep 14 '15 at 18:53
-
Doesn't work for me. Always returns 0. This is for the titleLabel within a button. – qazimusab Dec 14 '16 at 22:56
-
Swift 4
The answers above work well, but use some deprecated values/functions. Here's a fixed version that works in 2018.
func approximateAdjustedFontSizeWithLabel(_ label: UILabel) -> CGFloat {
var currentFont: UIFont = label.font
let originalFontSize = currentFont.pointSize
var currentSize: CGSize = (label.text! as NSString).size(withAttributes: [NSAttributedStringKey.font: currentFont])
while currentSize.width > label.frame.size.width && currentFont.pointSize > (originalFontSize * label.minimumScaleFactor) {
currentFont = currentFont.withSize(currentFont.pointSize - 1.0)
currentSize = (label.text! as NSString).size(withAttributes: [NSAttributedStringKey.font: currentFont])
}
return currentFont.pointSize
}

- 2,614
- 3
- 28
- 52

- 4,053
- 3
- 33
- 40
Check after the text has been applied (perhaps force a view reload first) you can grab the font size. For instance with a UITextField, you could implement the delegate method for textDidChange and then find out the font size from the font attribute on the textField. For a label, you could update the text then check the font size.
Example I built a project which updated a UILabel from a UITextField
-(void)textFieldDidEndEditing:(UITextField *)textField{
self.label.text = textField.text;
CGSize initialSize = [_label.text sizeWithAttributes:@{NSFontAttributeName:_label.font}];
while ( initialSize.width > _label.frame.size.width ) {
[_label setFont:[_label.font fontWithSize:_label.font.pointSize - 1]];
initialSize = [_label.text sizeWithAttributes:@{NSFontAttributeName:_label.font}];
}
CGFloat actualSize = _label.font.pointSize;
NSLog(@"acutal size %f",actualSize );
}
The actualSize seems right. (size calculation source)
-
I know how to auto shrink text. My problem is that I need to get the font size after the minimum font size/scale has been applied. – WaltersGE1 Feb 02 '15 at 18:19
-
Thanks for the idea. There were few problems with that solution, which I correct in my answer. – WaltersGE1 Feb 02 '15 at 19:43
All the solutions so far assume integer font sizes and fail to respect UILabel
's minimumScaleFactor
property.
Something like this should work:
+ (CGFloat)fontSizeForLabel:(UILabel *)label
{
if (label.adjustsFontSizeToFitWidth == NO || label.minimumScaleFactor >= 1.f) {
// font adjustment is disabled
return label.font.pointSize;
}
CGSize unadjustedSize = [_label.text sizeWithAttributes:@{NSFontAttributeName:_label.font}];
CGFloat scaleFactor = label.frame.size.width / unadjustedSize.width;
if (scaleFactor >= 1.f) {
// the text already fits at full font size
return label.font.pointSize;
}
// Respect minimumScaleFactor
scaleFactor = MAX(scaleFactor, minimumScaleFactor);
CGFloat newFontSize = label.font.pointSize * scaleFactor;
// Uncomment this if you insist on integer font sizes
//newFontSize = floor(newFontSize);
return newFontSize;
}

- 865
- 8
- 13