Tamaño de fuente personalizado en las classs de tamaño XCode6 no funciona correctamente con las fonts personalizadas

Xcode 6 tiene una nueva function en la que las fonts y los tamaños de fuente en UILabel, UITextField y UIButton se pueden configurar automáticamente en function de la class de tamaño de la configuration actual del dispositivo, directamente en el guión gráfico. Por ejemplo, puede configurar un UILabel para que use el tamaño de fuente 12 en "cualquier ancho, altura compacta" (como en iPhones en el paisaje) y el tamaño 18 en "ancho regular, altura regular" (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 realmente excelente en teoría porque podría hacer que no sea necesario progtwigr establecer diferentes fonts en las características de la interfaz de usuario basadas en la configuration del dispositivo. En este momento, tengo un código condicional que establece las fonts en function del tipo de dispositivo, pero obviamente eso significa que tengo que configurar las fonts programáticamente en todas partes de la aplicación. Así que inicialmente estaba muy entusiasmado con esta característica, pero descubrí que tiene un problema serio en el uso real para mí (quizás un error). Tenga en count que estoy construyendo contra el SDK 8 y estableciendo un objective mínimo de implementación de iOS 8, por lo que esto no tiene nada que ver con la compatibilidad con las versiones anteriores de iOS.

El problema es este: si configuro diferentes tamaños de letra para diferentes classs de tamaño y uso la fuente "Sistema" proporcionada por iOS, todo funciona como se espera y los tamaños de letra cambian según la class de tamaño. Si utilizo una fuente personalizada proporcionada por mi aplicación (sí, la tengo configurada correctamente en mi package de aplicaciones, ya que funciona mediante progtwigción) y establezco la fuente personalizada en una label en un storyboard XCode 6, que también funciona según lo esperado. Pero cuando trato de usar diferentes tamaños de la fuente personalizada para diferentes classs de tamaño, en el guión gráfico, de repente no funciona. La única diferencia en la configuration 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 pnetworkingeterminada del sistema en el tamaño pnetworkingeterminado, independientemente de la class de tamaño (y he verificado a través del depurador que está sustituyendo la fuente del sistema por la real especificada en el guión gráfico) . Entonces, básicamente, la function de class de tamaño parece estar rota para las fonts personalizadas. También, curiosamente, las fonts personalizadas realmente muestran y ajustan el tamaño correctamente en el panel XCode 6 "Vista previa" para el controller de visualización: 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 no parece funcionar para ninguna de ellas, pero siempre funciona si uso "Sistema" en su lugar.

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 las fonts de manera programática como lo hice con alnetworkingedor de 3 versiones de iOS, porque eso funciona. Pero me encantaría poder utilizar esta function si pudiera hacer que funcione con fonts personalizadas. El uso de la fuente del sistema no es aceptable para nuestro layout.


INFORMACIÓN ADICIONAL: a partir de Xcode 8.0, el error es corregido.

Solución rápida:

1) Establecer fonts como Sistema para classs de tamaño

Inspector de atributos de etiqueta

2) Subclass UILabel y reemplaza 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 probarlo todo, finalmente me decidí por 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 Storyboard
  • Utiliza un observador didSet , para evitar las trampas de layoutSubviews() (bucle infinito para las alturas de fila de vista de tabla dinámica) y awakeFromNib() (ver el comentario @ cocoaNoob)
  • Utiliza classs de tamaño en lugar del idioma del dispositivo, con la esperanza de eventualmente usar esto con @IBDesignable
  • Lamentablemente, @IBDesignable no funciona con traitCollection acuerdo con este otro artículo de la stack
  • La statement de cambio de característica de cambio 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 cambie la altura de su label en consecuencia en cada Clase de tamaño. Su label debe tener habilitado el cambio automático. Funcionó muy bien en mi caso.

Este error (y otras relacionadas con Xcode – Size Classes) me causó algún dolor grave recientemente, ya que tuve que pasar por un enorme file de storyboard que pirateaba las cosas.

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

En el file de encabezado de su subclass personalizada, use IBInspectable para sus attributes de time de ejecución. Esto hará que estos attributes sean accesibles desde el "Inspector de Atributos", visualmente justo arriba de la position pnetworkingeterminada para la configuration de la fuente.

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 útil este resultado:

introduzca la descripción de la imagen aquí

Un beneficio adicional es que ahora no tenemos que agregar los attributes de time de ejecución de forma manual para cada label. Esto es lo más cercano que podría llegar al comportamiento previsto de XCode. Es de esperar que se solucione el problema con iOS 9 este verano.

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 loops infinitos en algunos casos. Mi experiencia ha sido usarla junto con SwipeView .

En cambio, sugiero que:

1) Subclass UILabel y override setFont:

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

2) Establezca la class personalizada de sus UILabels y luego configure las classs de tamaño de fuente usando la fuente de Sistema

introduzca la descripción de la imagen aquí

El problema sigue estando allí que no puede usar la function para configurar Fonts para diferentes classs de tamaño desde el generador de interfaces.

Simplemente configure la fuente según el dispositivo que desee, como 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 sí lo hizo. También debe usar la fuente del sistema en IB

 #import <UIKit/UIKit.h> @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í. Debe deshabilitar primero el tamaño de fuente para las classs de tamaño en el generador de interfaces. 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 respuestas posteriores anteriores fue útil. A continuación, le explicamos cómo solucioné el error IB a través de una extensión Swift UILabel:

 import UIKit // This extension is only requinetworking 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. Así que 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 class en ExUILabel

  2. A continuación, vaya a Inspector de attributes en diseñador y configure el nombre de la fuente.

Se me ocurrió una solución aún más rápida (supongo que siempre usas tu única fuente personalizada).

Cree una categoría para UILabel e incluya en los files usando el guión gráfico de Buggy con las classs de tamaño y la configuration de fuente dedicada para varias classs:

 @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 de buggy usará la fuente del sistema en lugar de la propia, esta categoría lo cambiará a su fuente personalizada.

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

  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 label asignas una label de 100 a 110 (o más, pero 10 siempre fue suficiente para mí en un controller de vista).
  3. Luego, coloque este código en el file fuente de su VC y no olvide cambiar el nombre de la fuente. Codifique 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) } } } 
  • agregar fonts proporcionadas por la aplicación en su aplicación .plist
  • agregue su file .ttf al elemento 0
  • usarlo [UIFont fontWithName: tamaño "example.ttf": 10]