Establecer una fuente pnetworkingeterminada para toda la aplicación de iOS?

Tengo una fuente personalizada que quiero utilizar para mostrar todo el text en mi aplicación, tags, vistas de text, etc.

¿Hay alguna manera de configurar la fuente pnetworkingeterminada (tags por defecto usan SystemFont) para toda la aplicación?

Parece posible en iOS 5 usar el proxy UIAppearance.

  [[UILabel appearance] setFont:[UIFont fontWithName:@"YourFontName" size:17.0]]; 

Eso establecerá que la fuente sea cualquiera que sea su fuente personalizada para todos los UILabels en su aplicación. Deberá repetirlo para cada control (UIButton, UILabel, etc.).

Recuerde que necesitará poner el valor UIAppFonts en su info.plist e include el nombre de la fuente que está incluyendo.

También hay otra solución que será anular systemFont.

Simplemente crea una categoría

UIFont + SystemFontOverride.h

 #import <UIKit/UIKit.h> @interface UIFont (SystemFontOverride) @end 

UIFont + SystemFontOverride.m

 @implementation UIFont (SystemFontOverride) #pragma clang diagnostic push #pragma clang diagnostic ignonetworking "-Wobjc-protocol-method-implementation" + (UIFont *)boldSystemFontOfSize:(CGFloat)fontSize { return [UIFont fontWithName:@"fontName" size:fontSize]; } + (UIFont *)systemFontOfSize:(CGFloat)fontSize { return [UIFont fontWithName:@"fontName" size:fontSize]; } #pragma clang diagnostic pop @end 

Esto replaceá la implementación pnetworkingeterminada y la mayoría de los UIControls usan systemFont.

Si está usando Swift, puede crear una extensión UILabel:

 extension UILabel { var substituteFontName : String { get { return self.font.fontName } set { self.font = UIFont(name: newValue, size: self.font.pointSize) } } } 

Y luego, donde haces tu aparición proxy:

 UILabel.appearance().substituteFontName = applicationFont 

Existe un código equivalente de Objective-C que utiliza UI_APPEARANCE_SELECTOR en una propiedad con el nombre substituteFontName .

Adición

Para el caso en que desee establecer fonts en negrita y regulares por separado:

 extension UILabel { var substituteFontName : String { get { return self.font.fontName } set { if self.font.fontName.rangeOfString("Medium") == nil { self.font = UIFont(name: newValue, size: self.font.pointSize) } } } var substituteFontNameBold : String { get { return self.font.fontName } set { if self.font.fontName.rangeOfString("Medium") != nil { self.font = UIFont(name: newValue, size: self.font.pointSize) } } } } 

Entonces, para sus proxies UIAppearance:

 UILabel.appearance().substituteFontName = applicationFont UILabel.appearance().substituteFontNameBold = applicationFontBold 

Nota: si encuentra que la sustitución en negrita no funciona, es posible que el nombre de fuente pnetworkingeterminado no contenga "Medio". Cambie esa cadena por otra coincidencia según sea necesario (gracias a Mason en los comentarios a continuación).

Swift 3.1

Base en la respuesta de Fábio Oliveira ( https://stackoverflow.com/a/23042694/2082851 ), hago mi propio swift 3.1.

En resumen, esta extensión intercambia las funciones pnetworkingeterminadas init(coder:) , systemFont(ofSize:) , boldSystemFont(ofSize:) , italicSystemFont(ofSize:) con mis methods personalizados.

Tenga en count que no se implementa por completo, pero puede intercambiar más methods basados ​​en mi implementación.

 struct AppFontName { static let regular = "CourierNewPSMT" static let bold = "CourierNewPS-BoldMT" static let italic = "CourierNewPS-ItalicMT" } extension UIFont { class func mySystemFont(ofSize size: CGFloat) -> UIFont { return UIFont(name: AppFontName.regular, size: size)! } class func myBoldSystemFont(ofSize size: CGFloat) -> UIFont { return UIFont(name: AppFontName.bold, size: size)! } class func myItalicSystemFont(ofSize size: CGFloat) -> UIFont { return UIFont(name: AppFontName.italic, size: size)! } convenience init(myCoder aDecoder: NSCoder) { if let fontDescriptor = aDecoder.decodeObject(forKey: "UIFontDescriptor") as? UIFontDescriptor { if let fontAttribute = fontDescriptor.fontAttributes["NSCTFontUIUsageAttribute"] as? String { var fontName = "" switch fontAttribute { case "CTFontRegularUsage": fontName = AppFontName.regular case "CTFontEmphasizedUsage", "CTFontBoldUsage": fontName = AppFontName.bold case "CTFontObliqueUsage": fontName = AppFontName.italic default: fontName = AppFontName.regular } self.init(name: fontName, size: fontDescriptor.pointSize)! } else { self.init(myCoder: aDecoder) } } else { self.init(myCoder: aDecoder) } } class func overrideInitialize() { if self == UIFont.self { let systemFontMethod = class_getClassMethod(self, #selector(systemFont(ofSize:))) let mySystemFontMethod = class_getClassMethod(self, #selector(mySystemFont(ofSize:))) method_exchangeImplementations(systemFontMethod, mySystemFontMethod) let boldSystemFontMethod = class_getClassMethod(self, #selector(boldSystemFont(ofSize:))) let myBoldSystemFontMethod = class_getClassMethod(self, #selector(myBoldSystemFont(ofSize:))) method_exchangeImplementations(boldSystemFontMethod, myBoldSystemFontMethod) let italicSystemFontMethod = class_getClassMethod(self, #selector(italicSystemFont(ofSize:))) let myItalicSystemFontMethod = class_getClassMethod(self, #selector(myItalicSystemFont(ofSize:))) method_exchangeImplementations(italicSystemFontMethod, myItalicSystemFontMethod) let initCoderMethod = class_getInstanceMethod(self, #selector(UIFontDescriptor.init(coder:))) // Trick to get over the lack of UIFont.init(coder:)) let myInitCoderMethod = class_getInstanceMethod(self, #selector(UIFont.init(myCoder:))) method_exchangeImplementations(initCoderMethod, myInitCoderMethod) } } } class AppDelegate: UIResponder, UIApplicationDelegate { // Avoid warning of Swift 3.1 // Method 'initialize()' defines Objective-C class method 'initialize', which is not guaranteed to be invoked by Swift and will be disallowed in future versions override init() { super.init() UIFont.overrideInitialize() } ... } 

Desarrollando a partir de la respuesta de Hugues BR, pero utilizando el método swizzling, llegué a una solución que está cambiando con éxito todas las fonts a una fuente deseada en mi aplicación.

Un enfoque con Dynamic Type debería ser lo que debería search en iOS 7. La siguiente solución no usa Dynamic Type.


Notas:

  • el código siguiente, en su estado presentado, nunca fue enviado a la aprobación de Apple;
  • hay una versión más corta que pasó el envío de Apple, es decir sin el - initWithCoder: anular. Sin embargo, eso no cubrirá todos los casos;
  • el siguiente código está presente en una class que utilizo para configurar el estilo de mi aplicación, que está incluido en mi class AppDelegate, estando así disponible en todas partes y para todas las instancias de UIFont;
  • Estoy usando Zapfino aquí solo para hacer los cambios mucho más visibles;
  • cualquier mejora que pueda encontrar en este código es bienvenida.

Esta solución usa dos methods diferentes para lograr el resultado final. La primera es anular los methods de la class UIFont + systemFontWithSize: y similar a los que usan mis alternativas (aquí utilizo "Zapfino" para no dejar dudas de que la sustitución fue exitosa).

El otro método es anular - initWithCoder: método en UIFont para replace cualquier aparición de CTFontRegularUsage y similar por mis alternativas. Este último método fue necesario porque he encontrado que los objects UILabel codificados en files NIB no comtestingn los methods + systemFontWithSize: para get la fuente de su sistema y, en su lugar, los codifican como objects UICTFontDescriptor . He tratado de anular - awakeAfterUsingCoder: pero de alguna manera me pidieron todos los objects codificados en mi storyboard y causaron fallas. - awakeFromNib no me permitiría leer el object NSCoder .

 #import <objc/runtime.h> NSString *const FORegularFontName = @"Zapfino"; NSString *const FOBoldFontName = @"Zapfino"; NSString *const FOItalicFontName = @"Zapfino"; #pragma mark - UIFont category @implementation UIFont (CustomFonts) #pragma clang diagnostic push #pragma clang diagnostic ignonetworking "-Wobjc-protocol-method-implementation" + (void)replaceClassSelector:(SEL)originalSelector withSelector:(SEL)modifiedSelector { Method originalMethod = class_getClassMethod(self, originalSelector); Method modifiedMethod = class_getClassMethod(self, modifiedSelector); method_exchangeImplementations(originalMethod, modifiedMethod); } + (void)replaceInstanceSelector:(SEL)originalSelector withSelector:(SEL)modifiedSelector { Method originalDecoderMethod = class_getInstanceMethod(self, originalSelector); Method modifiedDecoderMethod = class_getInstanceMethod(self, modifiedSelector); method_exchangeImplementations(originalDecoderMethod, modifiedDecoderMethod); } + (UIFont *)regularFontWithSize:(CGFloat)size { return [UIFont fontWithName:FORegularFontName size:size]; } + (UIFont *)boldFontWithSize:(CGFloat)size { return [UIFont fontWithName:FOBoldFontName size:size]; } + (UIFont *)italicFontOfSize:(CGFloat)fontSize { return [UIFont fontWithName:FOItalicFontName size:fontSize]; } - (id)initCustomWithCoder:(NSCoder *)aDecoder { BOOL result = [aDecoder containsValueForKey:@"UIFontDescriptor"]; if (result) { UIFontDescriptor *descriptor = [aDecoder decodeObjectForKey:@"UIFontDescriptor"]; NSString *fontName; if ([descriptor.fontAttributes[@"NSCTFontUIUsageAttribute"] isEqualToString:@"CTFontRegularUsage"]) { fontName = FORegularFontName; } else if ([descriptor.fontAttributes[@"NSCTFontUIUsageAttribute"] isEqualToString:@"CTFontEmphasizedUsage"]) { fontName = FOBoldFontName; } else if ([descriptor.fontAttributes[@"NSCTFontUIUsageAttribute"] isEqualToString:@"CTFontObliqueUsage"]) { fontName = FOItalicFontName; } else { fontName = descriptor.fontAttributes[@"NSFontNameAttribute"]; } return [UIFont fontWithName:fontName size:descriptor.pointSize]; } self = [self initCustomWithCoder:aDecoder]; return self; } + (void)load { [self replaceClassSelector:@selector(systemFontOfSize:) withSelector:@selector(regularFontWithSize:)]; [self replaceClassSelector:@selector(boldSystemFontOfSize:) withSelector:@selector(boldFontWithSize:)]; [self replaceClassSelector:@selector(italicSystemFontOfSize:) withSelector:@selector(italicFontOfSize:)]; [self replaceInstanceSelector:@selector(initWithCoder:) withSelector:@selector(initCustomWithCoder:)]; } #pragma clang diagnostic pop @end 

Para completar la respuesta de Sandy Chapman , aquí hay una solución en Objective-C (coloque esta categoría en cualquier lugar donde desee cambiar UILabel ):

 @implementation UILabel (SubstituteFontName) - (void)setSubstituteFontName:(NSString *)name UI_APPEARANCE_SELECTOR { self.font = [UIFont fontWithName:name size:self.font.pointSize]; } @end 

Entonces, puedes cambiar la Apperance con:

 [[UILabel appearance] setSubstituteFontName:@"SourceSansPro-Light"]; 

Lo publiqué como una nueva respuesta y no como un comentario porque no tengo suficiente reputación.

COMENTARIO PARA SWIFT 3.0 Y ADVERTENCIA DE SWIFT

Puede eliminar el post de advertencia en línea:

 let initCoderMethod = class_getInstanceMethod(self, Selector("initWithCoder:")) 

Al replacelo con:

 let initCoderMethod = class_getInstanceMethod(self, #selector(UIFontDescriptor.init(coder:))) 

Probablemente no, es probable que tenga el set de la fuente en su control, pero puede facilitar el process centralizando de dónde obtienen los types de fuente, por ejemplo, si el delegado de la aplicación o alguna otra class común tiene un método que devuelva la fuente y cualquier cosa que necesite establecer la fuente pueden llamar a ese método, lo que ayudará en caso de que necesite cambiar su fuente, debe cambiarla en un lugar en lugar de en cualquier lugar donde configure las fonts … Otra alternativa puede ser crear subclasss de sus elementos de interfaz de usuario que configurarán automáticamente la fuente, pero eso podría ser un exceso.

Ninguna de estas soluciones funciona de forma universal en toda la aplicación. Una cosa que encontré para ayudar a administrar las fonts en Xcode es abrir el Storyboard como código fuente (hacer clic con el control y hacer clic en el guión gráfico en Navegador de files> "Abrir como"> "Fuente") y luego hacer un "find-and-replace".

El tipo de fuente siempre se establece en código y plumilla / guión gráfico.

Para el código, como dijo Hugues BR , hacerlo en una categoría puede resolver el problema.

Para la plumilla / guión gráfico, podemos utilizar el método Swizzling awakeFromNib para cambiar el tipo de fuente ya que el elemento UI de plumilla / guión gráfico siempre lo llama antes de aparecer en la pantalla.

Supongo que conoces Aspects . Es una biblioteca para progtwigr AOP, basada en el Método Swizzling. Creamos una categoría para UILabel, UIButton, UITextView para implementarlo.

UILabel:

 #import "UILabel+OverrideBaseFont.h" #import "Aspects.h" @implementation UILabel (OverrideBaseFont) + (void)load { [[self class]aspect_hookSelector:@selector(awakeFromNib) withOptions:AspectPositionAfter usingBlock:^(id<AspectInfo> aspectInfo) { UILabel* instance = [aspectInfo instance]; UIFont* font = [UIFont fontWithName:@"HelveticaNeue-light" size:instance.font.pointSize]; instance.font = font; }error:nil]; } @end 

UIButton:

 #import "UIButton+OverrideBaseFont.h" #import "Aspects.h" @implementation UIButton (OverrideBaseFont) + (void)load { [[self class]aspect_hookSelector:@selector(awakeFromNib) withOptions:AspectPositionAfter usingBlock:^(id<AspectInfo> aspectInfo) { UIButton* instance = [aspectInfo instance]; UILabel* label = instance.titleLabel; UIFont* font = [UIFont fontWithName:@"HelveticaNeue-light" size:label.font.pointSize]; instance.titleLabel.font = font; }error:nil]; } @end 

UITextField:

 #import "UITextField+OverrideBaseFont.h" #import "Aspects.h" @implementation UITextField (OverrideBaseFont) + (void)load { [[self class]aspect_hookSelector:@selector(awakeFromNib) withOptions:AspectPositionAfter usingBlock:^(id<AspectInfo> aspectInfo) { UITextField* instance = [aspectInfo instance]; UIFont* font = [UIFont fontWithName:@"HelveticaNeue-light" size:instance.font.pointSize]; instance.font = font; }error:nil]; } @end 

UITextView:

 #import "UITextView+OverrideBaseFont.h" #import "Aspects.h" @implementation UITextView (OverrideBaseFont) + (void)load { [[self class]aspect_hookSelector:@selector(awakeFromNib) withOptions:AspectPositionAfter usingBlock:^(id<AspectInfo> aspectInfo) { UITextView* instance = [aspectInfo instance]; UIFont* font = [UIFont fontWithName:@"HelveticaNeue-light" size:instance.font.pointSize]; instance.font = font; }error:nil]; } @end 

Eso es todo, puede cambiar HelveticaNeue-light a una macro con su nombre de fuente.

Para Swift 3

Todas las respuestas anteriores son correctas, pero lo he hecho de una manera muy diferente según el tamaño del dispositivo . Aquí, en la class ATFontManager, hice el tamaño de fuente pnetworkingeterminado que se define en la parte superior de la class como pnetworkingeterminadoFontSizeForIphone7Plus , este es el tamaño de fuente de iphone 7plus y iphone 6 plus y puedes cambiarlo de acuerdo a tus necesidades.

  class ATFontManager: UIFont{ class func setFont(iPhone7PlusFontSize: CGFloat? = nil,andFontName fontN : String = FontName.HelveticaNeue.rawValue) -> UIFont{ let defaultFontSizeForIphone7Plus : CGFloat = 16 switch ATDeviceDetector().screenType { case .iPhone4: if let fontSize = iPhone7PlusFontSize{ return UIFont(name: fontN, size: fontSize - 3)! } return UIFont(name: fontN, size: defaultFontSizeForIphone7Plus - 6)! case .iPhone5: if let fontSize = iPhone7PlusFontSize{ return UIFont(name: fontN, size: fontSize - 2)! } return UIFont(name: fontN, size: defaultFontSizeForIphone7Plus - 3)! case .iPhone6AndIphone7: if let fontSize = iPhone7PlusFontSize{ return UIFont(name: fontN, size: fontSize - 1)! } return UIFont(name: fontN, size: defaultFontSizeForIphone7Plus - 1)! case .iPhone6PAndIPhone7P: return UIFont(name: fontN, size: iPhone7PlusFontSize ?? defaultFontSizeForIphone7Plus)! case .ipadmini: if let fontSize = iPhone7PlusFontSize{ return UIFont(name: fontN, size: fontSize + 2)! } return UIFont(name: fontN, size: defaultFontSizeForIphone7Plus + 1)! case .ipadpro: if let fontSize = iPhone7PlusFontSize{ return UIFont(name: fontN, size: fontSize + 3)! } return UIFont(name: fontN, size: defaultFontSizeForIphone7Plus + 2)! default: return UIFont(name: fontN, size: iPhone7PlusFontSize ?? 15)! } } } 

He agregado cierto nombre de fuente, para más puedes agregar el nombre y tipo de fuente aquí.

  enum FontName : String { case HelveticaNeue = "HelveticaNeue" case HelveticaNeueUltraLight = "HelveticaNeue-UltraLight" case HelveticaNeueBold = "HelveticaNeue-Bold" case HelveticaNeueBoldItalic = "HelveticaNeue-BoldItalic" case HelveticaNeueMedium = "HelveticaNeue-Medium" case AvenirBlack = "Avenir-Black" case ArialBoldMT = "Arial-BoldMT" case HoeflerTextBlack = "HoeflerText-Black" case AMCAPEternal = "AMCAPEternal" } 

Esta class se refiere al detector de dispositivo para proporcionar un tamaño de fuente adecuado según el dispositivo.

 class ATDeviceDetector { var iPhone: Bool { return UIDevice().userInterfaceIdiom == .phone } var ipad : Bool{ return UIDevice().userInterfaceIdiom == .pad } enum ScreenType: String { case iPhone4 case iPhone5 case iPhone6AndIphone7 case iPhone6PAndIPhone7P case ipadmini case ipadpro case unknown } struct ScreenSize{ static let SCREEN_WIDTH = UIScreen.main.bounds.size.width static let SCREEN_HEIGHT = UIScreen.main.bounds.size.height static let SCREEN_MAX_LENGTH = max(ScreenSize.SCREEN_WIDTH,ScreenSize.SCREEN_HEIGHT) static let SCREEN_MIN_LENGTH = min(ScreenSize.SCREEN_WIDTH,ScreenSize.SCREEN_HEIGHT) } var screenType: ScreenType { switch ScreenSize.SCREEN_MAX_LENGTH { case 0..<568.0: return .iPhone4 case 568.0: return .iPhone5 case 667.0: return .iPhone6AndIphone7 case 736.0: return .iPhone6PAndIPhone7P case 1024.0: return .ipadmini case 1366.0: return .ipadpro default: return .unknown } } } 

Cómo utilizar. Espero que ayude.

 //for default label.font = ATFontManager.setFont() //if you want to provide as your demand. Here **iPhone7PlusFontSize** variable is denoted as font size for *iphone 7plus and iphone 6 plus*, and it **ATFontManager** class automatically handle. label.font = ATFontManager.setFont(iPhone7PlusFontSize: 15, andFontName: FontName.HelveticaNeue.rawValue) 

NUI es una alternativa al proxy UIAppearance. Le da control sobre la fuente (y muchos otros attributes) de una gran cantidad de types de elementos de interfaz de usuario a lo largo de su aplicación simplemente modificando una hoja de styles, que puede reutilizarse en varias aplicaciones.

Después de agregar una class NUILabel a sus tags, puede controlar fácilmente su fuente en la hoja de styles:

 LabelFontName String Helvetica 

Si tiene tags con diferentes tamaños de letra, puede controlar sus tamaños utilizando las tags de NUI, LargeLabel y SmallLabel, o incluso crear sus propias classs rápidamente.

Hemos logrado lo mismo en Swift -Xcode 7.2 usando el Controlador de vista principal y el Controlador de vista secundario (Herencia).

Archivo – Nuevo – Clase Cocoa Touch – ParentViewController.

  import UIKit import Foundation class ParentViewController: UIViewController { var appUIColor:UIColor = UIColor.networkingColor() var appFont:UIFont = UIFont(name: "Copperplate", size: 20)! override func viewDidLoad() { super.viewDidLoad() } func addStatusBar() { let view = UIView(frame: CGRect(x: 0.0, y: 0.0, width: UIScreen.mainScreen().bounds.size.width, height: 20.0) ) view.backgroundColor = appUIColor self.view.addSubview(view) } } 

Realice los controles secundarios de vista y asocie con un StoryBoard VC, agregue una label de text.

  import UIKit class FontTestController: ParentViewController { @IBOutlet var testLabel: UILabel! override func viewDidLoad() { super.viewDidLoad() testLabel.font = appFont testLabel.textColor = appUIColor } 

O Realice un UILabel Class personalizado (método Sub classing) y asocie las tags requeridas.

 import Foundation import UIKit class CustomFontLabel: UILabel { requinetworking init(coder aDecoder: NSCoder) { super.init(coder: aDecoder)! backgroundColor = ParentViewController().appUIColor font = ParentViewController().appFont textColor = UIColor.blackColor() } } 

Nota: La fuente y el color declarados en Parent VC se implementan en CustomFontLabel. La ventaja es que podemos modificar las properties de uilabel / cualquier vista juntas en algunos simples cambios en Parent VC.

2) 'for' loop UIView para sub vistas. Funciona solo en un VC en particular.

  override func viewWillLayoutSubviews() { for view in self.view.subviews { if view.isKindOfClass(UITextField) { UITextField.appearance().font = UIFont(name: "Copperplate", size: 20) } if view.isKindOfClass(UILabel) { UILabel.appearance().font = UIFont(name: "Copperplate", size: 20) } } }