¿Cómo se calcula el tamaño real del punto de fuente en iOS 7 (no en el rectángulo delimitador)?

Editar: la pregunta vinculada “duplicada” solo trata sobre el cálculo del rectángulo de texto. Necesito calcular el tamaño real de la letra después de que la etiqueta lo haya escalado, NO el tamaño de la cadena.

Este método ahora está en desuso:

size = [self sizeWithFont:font // 20 minFontSize:minFontSize // 14 actualFontSize:&actualFontSize // 16 forWidth:maxWidth lineBreakMode:self.lineBreakMode]; 

¿Cómo puedo calcular el tamaño de fuente de un UILabel ahora en iOS 7 cuando se reduce el tamaño del texto para que quepa?

Tengo el mismo problema, necesito saber el tamaño real para hacer que los otros UILabels coincidan en mi UIView.

Sé que no es una solución perfecta, pero tal vez sea útil para ti.

Mi solución es: en lugar de usar adjustsFontSizeToFitWidth , calculo “manualmente” el tamaño.

 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; 

Destilada de la respuesta de Julius Bahr en esta página, este método funciona perfectamente para obtener el tamaño real de la fuente una vez que se ha ajustado automáticamente:

 - (CGFloat)getActualFontSizeForLabel:(UILabel *)label { NSStringDrawingContext *labelContext = [NSStringDrawingContext new]; labelContext.minimumScaleFactor = label.minimumScaleFactor; NSAttributedString *attributedString = [[NSAttributedString alloc] initWithString:label.text attributes:@{ NSFontAttributeName: label.font }]; [attributedString boundingRectWithSize:label.frame.size options:NSStringDrawingUsesLineFragmentOrigin | NSStringDrawingUsesFontLeading context:labelContext]; CGFloat actualFontSize = label.font.pointSize * labelContext.actualScaleFactor; return actualFontSize; } 

Estoy usando esto en mi aplicación para obtener los tamaños de fuente para tres tags diferentes para las que necesito mantener los tamaños sincronizados y al mismo tiempo permitir que se reduzcan automáticamente para traducciones localizadas que pueden ser bastante más largas que sus contrapartes originales en inglés.

Llamo a ese método una vez para cada etiqueta, y luego, si no tienen el mismo valor, configuré los tamaños de fuente de la etiqueta al mínimo de los tres.

El uso de minFontSize quedó obsoleto en UILabel en iOS 6 y en las NSString dibujo NSString en iOS 7. Si desea usarlo y encontrar el tamaño de fuente real utilizado, debe utilizar el método obsoleto que mencionó en su pregunta.

El reemplazo de minFontSize es minimumScaleFactor . Si desea encontrar el factor de escala real utilizado, debe crear un NSStringDrawingContext y pasarlo en el boundingRectWithSize:options:attributes:context: message, como este:

 NSStringDrawingContext *context = [[NSStringDrawingContext alloc] init]; context.minimumScaleFactor = 0.7; [label.text boundingRectWithSize:CGSizeMake(maxWidth, HUGE_VAL) options:NSStringDrawingUsesLineFragmentOrigin attributes:@{ NSFontAttributeName: font } context:context]; CGFloat actualFontSize = font.pointSize * context.actualScaleFactor; 

Ampliando la respuesta de Ferran

Para expandir para llenar el ancho o alto, lo que ocurra primero

Versión Swift

 func getFontSizeToFitFrameOfLabel(label: UILabel) -> CGFloat { var initialSize : CGSize = label.text!.sizeWithAttributes([NSFontAttributeName : label.font]) if initialSize.width > label.frame.size.width || initialSize.height > label.frame.size.height { while initialSize.width > label.frame.size.width || initialSize.height > label.frame.size.height { label.font = label.font.fontWithSize(label.font.pointSize - 1) initialSize = label.text!.sizeWithAttributes([NSFontAttributeName : label.font]) } } else { while initialSize.width < label.frame.size.width && initialSize.height < label.frame.size.height { label.font = label.font.fontWithSize(label.font.pointSize + 1) initialSize = label.text!.sizeWithAttributes([NSFontAttributeName : label.font]) } // went 1 point too large so compensate here label.font = label.font.fontWithSize(label.font.pointSize - 1) } return label.font.pointSize; } 

Luego haga algo como esto para usarlo (digamos que su etiqueta se llama title1Label)

  title1Label.frame = CGRect(x: 0.0, y: 0.0, width: view.frame.size.width, height: view.frame.size.height) // sets font to some nonzero size to begin with, it will change up or down to fit the label's frame title1Label.font = UIFont(name: "Super Mario 256", size: 45.0) title1Label.font = title1Label.font.fontWithSize(getFontSizeToFitFrameOfLabel(title1Label)) // resize height to be a little larger than the font height title1Label.frame.size.height = title1Label.font.pointSize*1.3 

Versión Objetivo C:

 - (CGFloat) maxFontSize:(UILabel *)label{ CGSize initialSize = [label.text sizeWithAttributes:@{NSFontAttributeName:label.font}]; if (initialSize.width > label.frame.size.width || initialSize.height > label.frame.size.height) { while (initialSize.width > label.frame.size.width || initialSize.height > label.frame.size.height) { [label setFont:[label.font fontWithSize:label.font.pointSize - 1]]; initialSize = [label.text sizeWithAttributes:@{NSFontAttributeName:label.font}]; } } else { while (initialSize.width < label.frame.size.width && initialSize.height < label.frame.size.height) { [label setFont:[label.font fontWithSize:label.font.pointSize + 1]]; initialSize = [label.text sizeWithAttributes:@{NSFontAttributeName:label.font}]; } // went 1 point too large so compensate here [label setFont:[label.font fontWithSize:label.font.pointSize - 1]]; } return label.font.pointSize; } 

Mi misión específica ha sido ajustar el tamaño de la fuente en 2 tags por igual con los ajustesFontSizeToFitWidth habilitados. La solución funciona en iOS 6 y 7.

 + (void)sizeLabelFontToMinSizeFor:(UILabel *)label1 and:(UILabel *)label2 { NSStringDrawingContext *labelContext = [NSStringDrawingContext new]; labelContext.minimumScaleFactor = label1.minimumScaleFactor; NSAttributedString *attributedString1 = [[NSAttributedString alloc] initWithString:label1.text attributes:@{NSFontAttributeName : label1.font}]; // the NSStringDrawingUsesLineFragmentOrigin and NSStringDrawingUsesFontLeading options are magic [attributedString1 boundingRectWithSize:label1.frame.size options:NSStringDrawingUsesLineFragmentOrigin | NSStringDrawingUsesFontLeading context:labelContext]; CGFloat actualFontSize1 = label1.font.pointSize * labelContext.actualScaleFactor; labelContext = [NSStringDrawingContext new]; labelContext.minimumScaleFactor = label2.minimumScaleFactor; NSAttributedString *attributedString2 = [[NSAttributedString alloc] initWithString:label2.text attributes:@{NSFontAttributeName : label2.font}]; [attributedString2 boundingRectWithSize:label2.frame.size options:NSStringDrawingUsesLineFragmentOrigin | NSStringDrawingUsesFontLeading context:labelContext]; CGFloat actualFontSize2 = label2.font.pointSize * labelContext.actualScaleFactor; CGFloat minSize = MIN(actualFontSize1, actualFontSize2); label1.font = [UIFont fontWithName:RCDefaultFontName size:minSize]; label2.font = [UIFont fontWithName:RCDefaultFontName size:minSize]; } 

El siguiente código no es compatible con minFontSize y lineBreakMode, por lo que si los necesita, debe mejorarlo usted mismo:

 CGSize NSString_sizeWithFont(NSString * str, UIFont *font) { CGSize result; if (NO == [str respondsToSelector: @selector(sizeWithAttributes:)]) { // legacy way result = [str sizeWithFont: font]; } else { // modern way NSDictionary * dict = [NSDictionary dictionaryWithObjectsAndKeys: font, NSFontAttributeName, nil]; result = [str sizeWithAttributes: dict]; } return result; } UIFont * NSString_calcActualFont(NSString * str, UIFont * initialFont, CGSize sizeLimit, CGSize * actualSize) { const CGSize curSize = NSString_sizeWithFont(str, initialFont); CGFloat actualFontSize = initialFont.pointSize; actualFontSize *= MIN(sizeLimit.width / curSize.width, sizeLimit.height / curSize.height); UIFont * actualFont = [initialFont fontWithSize: floorf(actualFontSize)]; *actualSize = NSString_sizeWithFont(str, actualFont); return actualFont; } 

Solución simple para UILabel de una línea:

 //myLabel - initial label UILabel *fullSizeLabel = [UILabel new]; fullSizeLabel.font = myLabel.font; fullSizeLabel.text = myLabel.text; [fullSizeLabel sizeToFit]; CGFloat actualFontSize = myLabel.font.pointSize * (myLabel.bounds.size.width / fullSizeLabel.bounds.size.width); //correct, if new font size bigger than initial actualFontSize = actualFontSize < myLabel.font.pointSize ? actualFontSize : myLabel.font.pointSize; 

El código de Erik van der Neut funcionó para mí, así que lo traduje en Swift y lo envolví en una extensión UILabel:

 extension UILabel { public func actualFontSize()-> CGFloat { let context = NSStringDrawingContext() context.minimumScaleFactor = self.minimumScaleFactor let attributedString = NSAttributedString(string: self.text ?? "", attributes: [NSFontAttributeName: self.font]) attributedString.boundingRectWithSize(self.frame.size, options: [.UsesLineFragmentOrigin], context: context) return (self.font.pointSize * context.actualScaleFactor) } }