Tamaño de fuente personalizado en clases de tamaño XCode6 que no funciona correctamente con fonts personalizadas

Xcode 6 tiene una nueva función donde las fonts y los tamaños de fuente en UILabel, UITextField y UIButton se pueden establecer automáticamente en función de la clase de tamaño de la configuración actual del dispositivo, directamente en el guión gráfico. Por ejemplo, puede configurar un UILabel para usar el tamaño de letra 12 en configuraciones de “cualquier ancho, altura compacta” (como en iPhones en horizontal) y en el tamaño 18 en configuraciones de “ancho regular, altura normal” (como en iPads). Más información está disponible aquí:

https://developer.apple.com/library/content/documentation/UserExperience/Conceptual/AutolayoutPG/Size-ClassSpecificLayout.html

Esta es una característica muy buena en teoría porque podría hacer innecesario establecer programáticamente diferentes fonts en las características de la interfaz de usuario basadas en la configuración del dispositivo. En este momento, tengo un código condicional que establece las fonts según el tipo de dispositivo, pero obviamente eso significa que tengo que configurar las fonts mediante progtwigción en todas partes de la aplicación. Así que al principio estaba realmente entusiasmado con esta función, pero descubrí que tiene un problema grave en mi uso real (tal vez un error). Tenga en cuenta que estoy comstackndo contra el SDK 8 y estableciendo un objective de implementación mínimo para iOS 8, por lo que no tiene nada que ver con la compatibilidad con las versiones anteriores de iOS.

El problema es este: si configuro diferentes tamaños de fuente para diferentes clases de tamaño y uso la fuente “Sistema” proporcionada por iOS, todo funciona como se espera y los tamaños de fuente cambian según la clase de tamaño. Si uso una fuente personalizada proporcionada por mi aplicación (sí, la configuré correctamente en mi paquete de aplicaciones, ya que funciona programáticamente) y configuré la fuente personalizada en una etiqueta en un guión gráfico de XCode 6, eso también funciona como se esperaba. Pero cuando trato de usar diferentes tamaños de la fuente personalizada para diferentes clases de tamaño, en el guión gráfico, de repente no funciona. La única diferencia en la configuración es la fuente que he elegido (una personalizada frente a la fuente del sistema). En cambio, todas las fonts aparecen en el dispositivo y el simulador como la fuente del sistema predeterminada en el tamaño predeterminado, independientemente de la clase de tamaño (y verifiqué a través del depurador que está sustituyendo la fuente del sistema por la actual especificada en el guión gráfico) . Así que, básicamente, la función de clase de tamaño parece estar rota para las fonts personalizadas. Además, curiosamente, las fonts personalizadas muestran y ajustan el tamaño correctamente en el panel “Vista previa” de XCode 6 para el controlador de vista: solo cuando se ejecuta en el sistema iOS real deja de funcionar (lo que me hace pensar que lo estoy configurando) correctamente).

Probé varias fonts personalizadas diferentes y parece que no funciona para ninguna de ellas, pero siempre funciona si utilizo “Sistema”.

De todos modos, ¿alguien más ha visto este problema en Xcode 6? ¿Alguna idea sobre si esto es un error en iOS 8, Xcode o algo que estoy haciendo mal? La única solución que he encontrado, como dije, es continuar configurando programáticamente las fonts, como he estado haciendo con 3 versiones de iOS, porque eso funciona. Pero me encantaría poder utilizar esta función si pudiera hacerlo funcionar con fonts personalizadas. Usar la fuente del sistema no es aceptable para nuestro diseño.


INFORMACIÓN ADICIONAL: A partir de Xcode 8.0, el error se corrigió.

Solución rápida:

1) Establecer fonts como sistema para clases de tamaño

Etiqueta atributos inspector

2) Subclase UILabel y anula el método “layoutSubviews” como:

- (void)layoutSubviews { [super layoutSubviews]; // Implement font logic depending on screen size if ([self.font.fontName rangeOfString:@"bold" options:NSCaseInsensitiveSearch].location == NSNotFound) { NSLog(@"font is not bold"); self.font = [UIFont fontWithName:@"Custom regular Font" size:self.font.pointSize]; } else { NSLog(@"font is bold"); self.font = [UIFont fontWithName:@"Custom bold Font" size:self.font.pointSize]; } } 

Por cierto, es una técnica muy conveniente para fonts icónicas

Después de probar todo, eventualmente decidí una combinación de las soluciones anteriores. Usando Xcode 7.2, Swift 2.

 import UIKit class LabelDeviceClass : UILabel { @IBInspectable var iPhoneSize:CGFloat = 0 { didSet { if isPhone() { overrideFontSize(iPhoneSize) } } } @IBInspectable var iPadSize:CGFloat = 0 { didSet { if isPad() { overrideFontSize(iPadSize) } } } func isPhone() -> Bool { // return UIDevice.currentDevice().userInterfaceIdiom == .Phone return !isPad() } func isPad() -> Bool { // return UIDevice.currentDevice().userInterfaceIdiom == .Pad switch (UIScreen.mainScreen().traitCollection.horizontalSizeClass, UIScreen.mainScreen().traitCollection.verticalSizeClass) { case (.Regular, .Regular): return true default: return false } } func overrideFontSize(fontSize:CGFloat){ let currentFontName = self.font.fontName if let calculatedFont = UIFont(name: currentFontName, size: fontSize) { self.font = calculatedFont } } } 
  • @IBInspectable permite establecer el tamaño de fuente en el guión gráfico
  • Utiliza un observador didSet para evitar las trampas de layoutSubviews() (bucle infinito para alturas de fila de la vista de tabla dinámica) y awakeFromNib() (vea el comentario de @ cocoaNoob)
  • Utiliza clases de tamaño en lugar del idioma del dispositivo, con la esperanza de usarlo eventualmente con @IBDesignable
  • Lamentablemente, @IBDesignable no funciona con traitCollection acuerdo con este otro artículo de stack
  • La instrucción de cambio de recostackción de rasgos se realiza en UIScreen.mainScreen() lugar de self por este artículo de stack

Solución para UILabel : mantenga el mismo tamaño de fuente en todas las clases de tamaño, pero en su lugar cambie la altura de la etiqueta en consecuencia en cada clase de tamaño. Su etiqueta debe tener autoshrink habilitado. Funcionó muy bien en mi caso.

Este error (y otros relacionados con Xcode – Clases de tamaño) me causó un gran dolor recientemente, ya que tuve que pasar por un gran archivo de guiones gráficos que pirateaba las cosas.

Para cualquier otra persona en este puesto, me gustaría agregar algo sobre la respuesta de @ razor28 para aliviar el dolor.

En el archivo de encabezado de su subclase personalizada, use IBInspectable para sus atributos de tiempo de ejecución. Esto hará que estos atributos sean accesibles desde el “Inspector de Atributos”, visualmente justo arriba de la posición predeterminada para la configuración de fonts.

Ejemplo de uso:

 @interface MyCustomLabel : UILabel @property (nonatomic) IBInspectable NSString *fontType; @property (nonatomic) IBInspectable CGFloat iphoneFontSize; @property (nonatomic) IBInspectable CGFloat ipadFontSize; @end 

Esto producirá muy útilmente esta salida:

enter image description here

Un beneficio adicional es que ahora no tenemos que agregar los atributos de tiempo de ejecución manualmente para cada etiqueta. Esto es lo más cerca que podría estar del comportamiento previsto de XCode. Con suerte, una solución adecuada está en camino con iOS 9 este verano.

Una solución similar a la de @ razor28, pero creo que es un poco más universal. Además, funciona bien en versiones anteriores de iOS

https://gist.github.com/softmaxsg/8a3ce30331f9f07f023e

El error sigue siendo válido en XCode 7.0 GM.

La solución de Razor28 causa bucles infinitos en algunos casos. Mi experiencia ha sido con usarlo junto con SwipeView .

En cambio, te sugiero que:

1) Subclase UILabel e invalidar setFont:

 - (void)setFont:(UIFont *)font { font = [UIFont fontWithName:(@"Montserrat") size:font.pointSize]; [super setFont:font]; } 

2) Establezca la clase personalizada de sus UILabels y luego configure las clases de tamaño de fuente usando la fuente del sistema

enter image description here

El problema sigue ahí es que no puede usar la función para establecer Fuentes para diferentes clases de tamaño desde el constructor de interfaz.

Simplemente configure la fuente según el dispositivo que desee, tal como se muestra a continuación:

 if (Your Device is iPAd) //For iPad { [yourLabel setFont:[UIFont fontWithName:@"FontName" size:FontSize]]; } else //For Other Devices then iPad { [yourLabel setFont:[UIFont fontWithName:@"FontName" size:FontSize]]; } 

Esto funciona perfectamente en todos los dispositivos.

Ninguno de estos funcionó para mí, pero esto fue así. También necesita usar la fuente del sistema en IB

 #import  @interface UILabelEx : UILabel @end #import "UILabelEx.h" #import "Constants.h" @implementation UILabelEx - (void) traitCollectionDidChange: (UITraitCollection *) previousTraitCollection { [super traitCollectionDidChange: previousTraitCollection]; self.font = [UIFont fontWithName:APP_FONT size:self.font.pointSize]; } @end 

Todavía no hay una respuesta correcta firmada. Este código funciona bien para mí. Primero debe deshabilitar el tamaño de fuente para las clases de tamaño en el constructor de interfaz. En IB puede usar una fuente personalizada.

 - (void) traitCollectionDidChange: (UITraitCollection *) previousTraitCollection { [super traitCollectionDidChange: previousTraitCollection]; if ((self.traitCollection.verticalSizeClass != previousTraitCollection.verticalSizeClass) || self.traitCollection.horizontalSizeClass != previousTraitCollection.horizontalSizeClass) { self.textField.font = [UIFont fontWithName:textField.font.fontName size:17.f]; } } 

Una combinación de algunas de las últimas respuestas anteriores fueron útiles. Así es como resolví el error de IB a través de una extensión Swift UILabel:

 import UIKit // This extension is only required as a work-around to an interface builder bug in XCode 7.3.1 // When custom fonts are set per size class, they are reset to a small system font // In order for this extension to work, you must set the fonts in IB to System // We are switching any instances of ".SFUIDisplay-Bold" to "MuseoSans-700" and ".SFUIDisplay-Regular" to "MuseoSans-300" and keeping the same point size as specified in IB extension UILabel { override public func traitCollectionDidChange(previousTraitCollection: UITraitCollection?) { super.traitCollectionDidChange(previousTraitCollection) if ((traitCollection.verticalSizeClass != previousTraitCollection?.verticalSizeClass) || traitCollection.horizontalSizeClass != previousTraitCollection?.horizontalSizeClass) { //let oldFontName = "\(font.fontName)-\(font.pointSize)" if (font.fontName == systemFontRegular) { font = UIFont(name: customFontRegular, size: (font?.pointSize)!) //xlog.debug("Old font: \(oldFontName) -> new Font: \(font.fontName) - \(font.pointSize)") } else if (font.fontName == systemFontBold) { font = UIFont(name: customFontBold, size: (font?.pointSize)!) //xlog.debug("Old font: \(oldFontName) -> new Font: \(font.fontName) - \(font.pointSize)") } } } } 

Estoy usando Swift, XCode 6.4. Entonces esto es lo que hice

 import Foundation import UIKit @IBDesignable class ExUILabel: UILabel { @IBInspectable var fontName: String = "Default-Font" { didSet { self.font = UIFont(name: fontName, size:self.font.pointSize) } } override func layoutSubviews() { super.layoutSubviews() self.font = UIFont(name: fontName, size:self.font.pointSize) } } 
  1. Goto Designer -> Identity Inspector -> Establezca la clase en ExUILabel

  2. Luego vaya al inspector de atributos en el diseñador y establezca el nombre de la fuente.

He encontrado una solución aún más rápida (supongo que siempre usas tu fuente personalizada).

Cree una categoría para UILabel e inclúyala en los archivos que usan el guión gráfico erróneo con clases de tamaño y configuración de fuente dedicada para varias clases:

 @implementation UILabel (FontFixForSizeClassesAppleBug) - (void)layoutSubviews { [super layoutSubviews]; if([[UIFont systemFontOfSize:10].familyName isEqualToString:self.font.familyName]) { //workaround for interface builder size classes bug which ignores custom font if various classes defined for label: http://stackoverflow.com/questions/26166737/custom-font-sizing-in-xcode6-size-classes-not-working-properly-w-custom-fonts self.font = [UIFont fontWithName:@"YOUR_CUSTOM_FONT_NAME" size:self.font.pointSize]; } } @end 

Simplemente use sus fonts personalizadas en el guión gráfico. Cuando el intérprete con errores use la fuente del sistema en su lugar, esta categoría la cambiará a su fuente personalizada.

Tuve el mismo problema y encontré una solución no muy clara, ¡pero excelente!

  1. Primero establece el tamaño de fuente requerido en el guión gráfico con el nombre de la fuente del sistema.
  2. Luego, a esta etiqueta le asigna una etiqueta de 100 a 110 (o más, pero 10 siempre fue suficiente para mí en un controlador de vista).
  3. Luego coloque este código en el archivo fuente de su CV y ​​no olvide cambiar el nombre de la fuente. Código en swift.
 override func viewDidLayoutSubviews() { for i in 100...110 { if let label = view.viewWithTag(i) as? UILabel { label.font = UIFont(name: "RotondaC-Bold", size: label.font.pointSize) } } } 
  • agregue las fonts proporcionadas por la aplicación en su aplicación .plist
  • agrega tu archivo .ttf al elemento 0
  • Úselo [UIFont fontWithName: “example.ttf” size: 10]