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

155

Tengo una fuente personalizada que quiero usar para todo lo que muestre texto en mi aplicación, etiquetas, vistas de texto, etc.

¿Hay alguna manera de configurar la fuente predeterminada (las etiquetas usan SystemFont de manera predeterminada) para toda la aplicación?

Sam Jarman
fuente
77
Habiendo investigado masivamente este infortunio. Honestamente, hemos descubierto que lo más simple es crear una nueva clase (trivial) para cada control. Entonces, para UIButton, crea SJButton. No olvide anular initWithFrame e initWithCode. Para cada control (por ejemplo, UIButton, etc.) configure los colores o lo que quiera. Elija cuidadosamente el tamaño (es decir, será el tamaño SET EN EL STORYBOARD) en el código int y luego (como prefiera) use ese tamaño (y configure, digamos, la fuente, el color, lo que sea). Es solo unas pocas líneas de código, es increíblemente ordenado y le ahorra mucho tiempo a largo plazo.
Fattie
@JoeBlow Gracias por publicar sus hallazgos, estaba a punto de pasar el tiempo buscando responder yo mismo
jj.
@ jj- Correcto. No olvides que debes usar IBDesignableestos días. Espero eso ayude. Considere también este interesante QA: stackoverflow.com/a/38000466/294884
Fattie

Respuestas:

158

Parece posible en iOS 5 usando el proxy UIAppearance.

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

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

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

Randall
fuente
46
Gracias por la respuesta. Pude hacer que esto funcione. ¿Sabes si hay una manera de especificar la fuente sin especificar el tamaño de la fuente? Tengo etiquetas en mi aplicación que no comparten el mismo tamaño de fuente.
Brandon
23
¿Puedo hacer esto sin anular el tamaño en puntos de cada instancia?
Michael Forrest
17
setFont:el método está en desuso
Anand
12
@ ¿Y estás seguro de esto? No lo veo marcado como obsoleto en UILabel. Está en desuso UIButtonpero usa la fuente para la titleLabelpropiedad, que es a UILabel, por lo que solo UILabeldebería estar bien configurar la fuente con el proxy de apariencia .
Adrian Schönig
66
@Anand no está en desuso para UILabel.
Alastair Stuart
118

Swift 5

Basado en la respuesta de Fábio Oliveira ( https://stackoverflow.com/a/23042694/2082851 ), hago mi propio 4 rápido.

En resumen, este intercambio funciones de extensión predeterminada init(coder:), systemFont(ofSize:), boldSystemFont(ofSize:),italicSystemFont(ofSize:) con mis métodos personalizados.

Tenga en cuenta que no se implementa completamente, pero puede intercambiar más métodos basados ​​en mi implementación.

import UIKit

struct AppFontName {
    static let regular = "CourierNewPSMT"
    static let bold = "CourierNewPS-BoldMT"
    static let italic = "CourierNewPS-ItalicMT"
}

extension UIFontDescriptor.AttributeName {
    static let nsctFontUIUsage = UIFontDescriptor.AttributeName(rawValue: "NSCTFontUIUsageAttribute")
}

extension UIFont {
    static var isOverrided: Bool = false

    @objc class func mySystemFont(ofSize size: CGFloat) -> UIFont {
        return UIFont(name: AppFontName.regular, size: size)!
    }

    @objc class func myBoldSystemFont(ofSize size: CGFloat) -> UIFont {
        return UIFont(name: AppFontName.bold, size: size)!
    }

    @objc class func myItalicSystemFont(ofSize size: CGFloat) -> UIFont {
        return UIFont(name: AppFontName.italic, size: size)!
    }

    @objc convenience init(myCoder aDecoder: NSCoder) {
        guard
            let fontDescriptor = aDecoder.decodeObject(forKey: "UIFontDescriptor") as? UIFontDescriptor,
            let fontAttribute = fontDescriptor.fontAttributes[.nsctFontUIUsage] as? String else {
                self.init(myCoder: aDecoder)
                return
        }
        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)!
    }

    class func overrideInitialize() {
        guard self == UIFont.self, !isOverrided else { return }

        // Avoid method swizzling run twice and revert to original initialize function
        isOverrided = true

        if let systemFontMethod = class_getClassMethod(self, #selector(systemFont(ofSize:))),
            let mySystemFontMethod = class_getClassMethod(self, #selector(mySystemFont(ofSize:))) {
            method_exchangeImplementations(systemFontMethod, mySystemFontMethod)
        }

        if let boldSystemFontMethod = class_getClassMethod(self, #selector(boldSystemFont(ofSize:))),
            let myBoldSystemFontMethod = class_getClassMethod(self, #selector(myBoldSystemFont(ofSize:))) {
            method_exchangeImplementations(boldSystemFontMethod, myBoldSystemFontMethod)
        }

        if let italicSystemFontMethod = class_getClassMethod(self, #selector(italicSystemFont(ofSize:))),
            let myItalicSystemFontMethod = class_getClassMethod(self, #selector(myItalicSystemFont(ofSize:))) {
            method_exchangeImplementations(italicSystemFontMethod, myItalicSystemFontMethod)
        }

        if 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
    // 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()
    }
    ...
}
nahung89
fuente
2
¡¡la mejor respuesta!! anular automáticamente la fuente del sistema, brillante
Kappe
2
Si alguien tiene problemas con la línea "NSCTFontUIUsageAttribute": if let fontAttribute = fontDescriptor.fontAttributes[.nsctFontUIUsage] as? String {hizo el truco para mí.
Conocimiento
1
no parece funcionar con UILabels que establezcan estilo de texto (negrita, título, título, etc.) ... solo funciona con fuentes que tienen un tamaño específico y un conjunto de fuentes del sistema. @ nahung89
aviran
1
Esto también cambia algunas fuentes de la interfaz de usuario del sistema. Por ejemplo, la lista de sugerencias de teclado y la hoja de acciones. No sé si esto hará que Apple rechace la aplicación
Henry H Miao
1
Ha pasado un año desde que se publicó esta respuesta. ¿Alguien tiene una manera más "nativa" de Apple para lograr esto?
Greg Hilston
75

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

Solo 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 ignored "-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 reemplazará la implementación predeterminada y la mayoría de UIControls usan systemFont.

Hugues BR
fuente
1
¿Está esto dentro de las pautas de Apple?
Rambatino
Es más un truco. No he agregado mi registro de aplicaciones con este truco, ya que no está utilizando ningún método privado. Si desea una solución más sólida, también le sugiero que compruebe esto: github.com/0xced/FontReplacer
Hugues BR
2
Esto esta bien. Apple simplemente no quiere que uses funciones indocumentadas. Se le permite "mezclar" métodos que son públicos.
mxcl
44
Cuando una categoría tiene métodos con la misma firma que la clase, está extendiendo el comportamiento no está definido. Para reemplazar los métodos de clase, debe usar el método swizzling (que tampoco es una buena idea).
GreatWiz
1
Como otros han señalado, esta solución, si bien es probable que sea efectiva la mayor parte del tiempo, técnicamente está introduciendo el potencial de un comportamiento indefinido. Si no tiene ganas de arriesgarse, el método swizzling podría ser una mejor opción. La respuesta aquí proporciona la misma solución a través de swizzling: stackoverflow.com/questions/19542942/…
Nathan Hosselton
64

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

extension UILabel {

    @objc 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

Hay un código equivalente de Objective-C que se usa UI_APPEARANCE_SELECTORen una propiedad con el nombre substituteFontName.

Adición

Para el caso en el que desea establecer fuentes en negrita y regulares por separado:

extension UILabel {

    @objc var substituteFontName : String {
        get { return self.font.fontName }
        set { 
            if self.font.fontName.range(of:"Medium") == nil { 
                self.font = UIFont(name: newValue, size: self.font.pointSize)
            }
        }
    }

    @objc var substituteFontNameBold : String {
        get { return self.font.fontName }
        set { 
            if self.font.fontName.range(of:"Medium") != nil { 
                self.font = UIFont(name: newValue, size: self.font.pointSize)
            }
        }
    }
}

Luego, para sus proxies de apariencia UIA:

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

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

Sandy Chapman
fuente
Una desventaja de esto que he encontrado es que cuando inicio alertas con UIAlertController, el botón con el estilo .Cancel es el mismo que el botón con el estilo .Default (al menos cuando uso GillSans). Mientras que normalmente .Cancel sería una fuente de peso normal, y .Default estaría en negrita. ¿Algunas ideas?
Mason G. Zhwiti
Lo siento, quise decir. Las etiquetas de cancelación normalmente estarían en negrita, y el valor predeterminado normalmente sería de peso normal.
Mason G. Zhwiti
2
@ MasonG.Zhwiti En ese caso, probablemente configuré la UILabelextensión para tomar un nombre de fuente adicional en negrita. Luego, sethaga una comprobación para ver si "Negrita" está en el nombre de la fuente e ignore el conjunto en un caso, y úselo en el otro. Editaré y agregaré un ejemplo.
Sandy Chapman
@SandyChapman ¡Gracias! Estoy probando esta nueva técnica, y tiene sentido, pero no parece estar funcionando para mí. Estoy usando GillSans y GillSans-Bold en el simulador iOS 8.3. ¿Has probado esta técnica?
Mason G. Zhwiti
2
@ Sandy Chapman Me di cuenta de lo que está pasando. Las fuentes predeterminadas para iOS 8 tienden a ser HelveticaNeueInterface-Regular o (en negrita) HelveticaNeueInterface-MediumP4. Por lo tanto, buscar "Bold" nunca fue nada. Lo cambié rangeOfString("Medium")y funcionó.
Mason G. Zhwiti
23

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 fuentes a una fuente deseada en mi aplicación.

Un enfoque con Dynamic Type debería ser lo que debe buscar en iOS 7. La siguiente solución no está usando Dynamic Type.


Notas:

  • el siguiente código, en su estado presentado, nunca se sometió a la aprobación de Apple;
  • hay una versión más corta que pasó la presentación de Apple, sin - initWithCoder:anulación. Sin embargo, eso no cubrirá todos los casos;
  • el siguiente código está presente en una clase que uso para establecer el estilo de mi aplicación que está incluida en mi clase AppDelegate, por lo que está disponible en todas partes y para todas las instancias de UIFont;
  • Estoy usando Zapfino aquí solo para hacer que los cambios sean mucho más visibles;
  • Cualquier mejora que pueda encontrar en este código es bienvenida.

Esta solución utiliza dos métodos diferentes para lograr el resultado final. El primero es anular los métodos de clase UIFont + systemFontWithSize:y similares con los que usan mis alternativas (aquí uso "Zapfino" para no dejar dudas de que el reemplazo fue exitoso).

El otro método es anular el - initWithCoder:método en UIFont para reemplazar cualquier ocurrencia CTFontRegularUsagey similar por mis alternativas. Este último método fue necesario porque descubrí que los UILabelobjetos codificados en archivos NIB no verifican los + systemFontWithSize:métodos para obtener la fuente de su sistema y, en cambio, los codifican como UICTFontDescriptorobjetos. Intenté anular, - awakeAfterUsingCoder:pero de alguna manera se estaba llamando para cada objeto codificado en mi guión gráfico y provocaba bloqueos. Anular - awakeFromNibno me permitiría leer el NSCoderobjeto.

#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 ignored "-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
Fábio Oliveira
fuente
Cómo utiliza esta implementación en iOS6 que no tiene UIFontDescriptor
Utku Yıldırım
He usado la clave del decodificador "UIFontTraits" para verificar si la fuente proporcionada está en negrita o cursiva y reemplazarla con mis propias variaciones. Lo obtuve de esta esencia aquí gist.github.com/Daij-Djan/5046612 .
Fábio Oliveira
Gracias por responder, utilicé otra solución por ahora. Lo comprobaré cuando lo necesite de nuevo :)
Utku Yıldırım
2
gracias @ FábioOliveira, ¡funciona de maravilla! Solo una cosa más que necesita para poner #import <objc / runtime.h> en el encabezado, de lo contrario obtendrá un error al usar la clase 'Método' (error que obtengo en XCode 6)
nahung89
Por alguna razón, en iOS 8, modals ( UIAlertController) no cambia la fuente.
Randomblue
13

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

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

El archivo de interfaz debe tener este método declarado públicamente para su uso posterior desde lugares como el delegado de su aplicación:

@interface UILabel (FontOverride)
  - (void)setSubstituteFontName:(NSString *)name UI_APPEARANCE_SELECTOR;
@end

Luego, puede cambiar el Appearancecon:

[[UILabel appearance] setSubstituteFontName:@"SourceSansPro-Light"];
Damien Debin
fuente
1
Hola, ¿te refieres a "en cualquier lugar", ese código tendría que agregarse en cada controlador de vista y usar cada UILabel en el controlador, donde desea cambiar la fuente?
Jules
No, debe poner este código una vez , en cualquier parte de su proyecto; en su appdelegate por ejemplo.
Damien Debin
1
@DamienDebin Quiero usar negrita para negrita, pero esto cambia de negrita a claro. Alguna forma de vuelta?
Zeeshan
En realidad, funciona, pero ¿debería ser "Categoría" o "Extensión"? La diferencia se explica aquí: stackoverflow.com/questions/7136124/…
Darius Miliauskas
4

COMENTARIO PARA SWIFT 3.0 Y SWIFT WARNING

Puede eliminar el mensaje de advertencia en línea:

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

Al reemplazarlo con:

let initCoderMethod = class_getInstanceMethod(self, #selector(UIFontDescriptor.init(coder:)))
ucotta
fuente
Jajaja No sabía que Swift permitiera usar esto. Por cierto, lo actualizaré a la respuesta anterior. Gracias @ucotta!
nahung89
4

Para Swift 5

Todas las respuestas anteriores son correctas, pero lo he hecho de manera poco diferente según el tamaño del dispositivo . Aquí, en la clase ATFontManager, he hecho el tamaño de fuente predeterminado que se define en la parte superior de la clase como defaultFontSize , este es el tamaño de fuente de iphone plus y puede cambiar según sus requisitos.

class ATFontManager: UIFont{
    
    class func setFont( _ iPhone7PlusFontSize: CGFloat? = nil,andFontName fontN : String = FontName.helveticaNeue) -> UIFont{
        
        let defaultFontSize : CGFloat = 16
        
        switch ATDeviceDetector().screenType {
            
        case .iPhone4:
            if let fontSize = iPhone7PlusFontSize{
                return UIFont(name: fontN, size: fontSize - 5)!
            }
            return UIFont(name: fontN, size: defaultFontSize - 5)!
            
        case .iPhone5:
            if let fontSize = iPhone7PlusFontSize{
                return UIFont(name: fontN, size: fontSize - 3)!
            }
            return UIFont(name: fontN, size: defaultFontSize - 3)!
            
        case .iPhone6AndIphone7, .iPhoneUnknownSmallSize:
            if let fontSize = iPhone7PlusFontSize{
                return UIFont(name: fontN, size: fontSize - 2)!
            }
            return UIFont(name: fontN, size: defaultFontSize - 2)!
            
        case .iPhone6PAndIPhone7P, .iPhoneUnknownBigSize:
            
            return UIFont(name: fontN, size: iPhone7PlusFontSize ?? defaultFontSize)!
        case .iPhoneX, .iPhoneXsMax:
            
            return UIFont(name: fontN, size: iPhone7PlusFontSize ?? defaultFontSize)!
          
        case .iPadMini:
            if let fontSize = iPhone7PlusFontSize{
                return UIFont(name: fontN, size: fontSize + 2)!
            }
            return UIFont(name: fontN, size: defaultFontSize + 2)!
            
        case .iPadPro10Inch:
            if let fontSize = iPhone7PlusFontSize{
                return UIFont(name: fontN, size: fontSize + 4)!
            }
            return UIFont(name: fontN, size: defaultFontSize + 4)!
            
        case .iPadPro:
            if let fontSize = iPhone7PlusFontSize{
                return UIFont(name: fontN, size: fontSize + 6)!
            }
            return UIFont(name: fontN, size: defaultFontSize + 6)!
            
        case .iPadUnknownSmallSize:
            
            return UIFont(name: fontN, size: defaultFontSize + 2)!
            
        case .iPadUnknownBigSize:
            
            return UIFont(name: fontN, size: defaultFontSize + 4)!
            
        default:
            
            return UIFont(name: fontN, size: iPhone7PlusFontSize ?? 16)!
        }
    }
}
     

He agregado cierto nombre de fuente, para más puede agregar el nombre de fuente y escribir 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 clase se refiere al detector de dispositivo para proporcionar el tamaño de fuente apropiado según el dispositivo.

class ATDeviceDetector {
    
    var iPhone: Bool {
        
        return UIDevice().userInterfaceIdiom == .phone
    }
    
    var ipad : Bool{
        
        return UIDevice().userInterfaceIdiom == .pad
    }
    
    let isRetina = UIScreen.main.scale >= 2.0
    
    
    enum ScreenType: String {
        
        case iPhone4
        case iPhone5
        case iPhone6AndIphone7
        case iPhone6PAndIPhone7P
        case iPhoneX
        
        case iPadMini
        case iPadPro
        case iPadPro10Inch
        
        case iPhoneOrIPadSmallSizeUnknown
        case iPadUnknown
        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 812.0:
            return .iPhoneX
        case 568.0..<812.0:
            return .iPhoneOrIPadSmallSizeUnknown
        case 1112.0:
            return .iPadPro10Inch
        case 1024.0:
            return .iPadMini
        case 1366.0:
            return .iPadPro
        case 812.0..<1366.0:
            return .iPadUnknown
        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)
Amrit Tiwari
fuente
3

Ninguna de estas soluciones funciona universalmente en toda la aplicación. Una cosa que encontré para ayudar a administrar las fuentes en Xcode es abrir Storyboard como código fuente (Control-clic en storyboard en el navegador de archivos> "Abrir como"> "Fuente"), y luego hacer una búsqueda y reemplazo.

Gingi
fuente
3

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

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

Para nib / storyboard, podemos usar Method Swizzling wakekeFromNib para cambiar el tipo de fuente, ya que el elemento de la interfaz de usuario de nib / storyboard siempre lo llama antes de mostrarlo en la pantalla.

Supongo que conoces Aspectos . Es una biblioteca para la programación de AOP, basada en Method Swizzling. Creamos 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.

Peng Xiaofeng
fuente
3

Creé mi propia conversión de tipografía para Swift 4 después de revisar algunas publicaciones, cubre la mayoría de los casos, como:

Primero Agregue fuentes a la estructura del proyecto y al archivo .plist (con el mismo nombre):

<key>UIAppFonts</key>
<array>
    <string>Typo-Light.ttf</string>
    <string>Typo-Regular.ttf</string>
    <string>Typo-Semibold.ttf</string>
    <string>Typo-LightItalic.ttf</string>
</array>

Luego

struct Resources {

    struct Fonts {
        //struct is extended in Fonts
    }
}

extension Resources.Fonts {

    enum Weight: String {
        case light = "Typo-Light"
        case regular = "Typo-Regular"
        case semibold = "Typo-Semibold"
        case italic = "Typo-LightItalic"
    }
}

extension UIFontDescriptor.AttributeName {
    static let nsctFontUIUsage = UIFontDescriptor.AttributeName(rawValue: "NSCTFontUIUsageAttribute")
}

extension UIFont {

    @objc class func mySystemFont(ofSize: CGFloat, weight: UIFont.Weight) -> UIFont {
        switch weight {
        case .semibold, .bold, .heavy, .black:
            return UIFont(name: Resources.Fonts.Weight.semibold.rawValue, size: ofSize)!

        case .medium, .regular:
            return UIFont(name: Resources.Fonts.Weight.regular.rawValue, size: ofSize)!

        default:
            return UIFont(name: Resources.Fonts.Weight.light.rawValue, size: ofSize)!
        }
    }

    @objc class func mySystemFont(ofSize size: CGFloat) -> UIFont {
        return UIFont(name: Resources.Fonts.Weight.light.rawValue, size: size)!
    }

    @objc class func myBoldSystemFont(ofSize size: CGFloat) -> UIFont {
        return UIFont(name: Resources.Fonts.Weight.semibold.rawValue, size: size)!
    }

    @objc class func myItalicSystemFont(ofSize size: CGFloat) -> UIFont {
        return UIFont(name: Resources.Fonts.Weight.italic.rawValue, size: size)!
    }

    @objc convenience init(myCoder aDecoder: NSCoder) {
        guard
            let fontDescriptor = aDecoder.decodeObject(forKey: "UIFontDescriptor") as? UIFontDescriptor,
            let fontAttribute = fontDescriptor.fontAttributes[.nsctFontUIUsage] as? String else {
                self.init(myCoder: aDecoder)
                return
        }
        var fontName = ""
        switch fontAttribute {
        case "CTFontRegularUsage", "CTFontMediumUsage":
            fontName = Resources.Fonts.Weight.regular.rawValue
        case "CTFontEmphasizedUsage", "CTFontBoldUsage", "CTFontSemiboldUsage","CTFontHeavyUsage", "CTFontBlackUsage":
            fontName = Resources.Fonts.Weight.semibold.rawValue
        case "CTFontObliqueUsage":
            fontName = Resources.Fonts.Weight.italic.rawValue
        default:
            fontName = Resources.Fonts.Weight.light.rawValue
        }
        self.init(name: fontName, size: fontDescriptor.pointSize)!
    }

    class func overrideDefaultTypography() {
        guard self == UIFont.self else { return }

        if let systemFontMethodWithWeight = class_getClassMethod(self, #selector(systemFont(ofSize: weight:))),
            let mySystemFontMethodWithWeight = class_getClassMethod(self, #selector(mySystemFont(ofSize: weight:))) {
            method_exchangeImplementations(systemFontMethodWithWeight, mySystemFontMethodWithWeight)
        }

        if let systemFontMethod = class_getClassMethod(self, #selector(systemFont(ofSize:))),
            let mySystemFontMethod = class_getClassMethod(self, #selector(mySystemFont(ofSize:))) {
            method_exchangeImplementations(systemFontMethod, mySystemFontMethod)
        }

        if let boldSystemFontMethod = class_getClassMethod(self, #selector(boldSystemFont(ofSize:))),
            let myBoldSystemFontMethod = class_getClassMethod(self, #selector(myBoldSystemFont(ofSize:))) {
            method_exchangeImplementations(boldSystemFontMethod, myBoldSystemFontMethod)
        }

        if let italicSystemFontMethod = class_getClassMethod(self, #selector(italicSystemFont(ofSize:))),
            let myItalicSystemFontMethod = class_getClassMethod(self, #selector(myItalicSystemFont(ofSize:))) {
            method_exchangeImplementations(italicSystemFontMethod, myItalicSystemFontMethod)
        }

        if let initCoderMethod = class_getInstanceMethod(self, #selector(UIFontDescriptor.init(coder:))),
            let myInitCoderMethod = class_getInstanceMethod(self, #selector(UIFont.init(myCoder:))) {
            method_exchangeImplementations(initCoderMethod, myInitCoderMethod)
        }
    }
}

Finalmente llame al método creado en el Appdelegatesiguiente:

class AppDelegate: UIResponder, UIApplicationDelegate {
    func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey : Any]? = nil) -> Bool {

        UIFont.overrideDefaultTypography()
        return true
    }
}
Javier Amor Penas
fuente
@sheshnath ¿puedes darnos más información sobre el choque?
Javier Amor Penas
1
lo siento, el error fue de mi parte, la fuente no figuraba en info.plist
nath
@midhunp ¿Podría ser más explícito para que no funcione para usted? A mí me funciona bien con tipografía en negrita.
Javier Amor Penas
2

Probablemente no, probablemente tendrá que configurar la fuente en su control usted mismo, pero puede facilitar el proceso centralizando de dónde obtiene los tipos de fuente, por ejemplo, delegue la aplicación o alguna otra clase común tenga un método que devuelva el fuente, y cualquier cosa que necesite configurar la fuente puede llamar a ese método, que ayudará en caso de que necesite cambiar su fuente, la cambiaría en un lugar en lugar de en cualquier lugar donde configure las fuentes ... Otra alternativa puede ser hacer subclases de sus elementos de la interfaz de usuario que establecerán automáticamente la fuente, pero eso podría ser excesivo ...

Daniel
fuente
para que conste, esto es lo que hice, pero @Randall necesitaba el representante y proporcionó una buena respuesta. Solo necesito soportar menos de 5.0
Sam Jarman
44
No estoy de acuerdo con lo que hiciste. La respuesta que seleccionó no es válida cuando su pregunta está etiquetada iphone-sdk-4.0.
Paulo Casaretto
@ Sam Jarman, la respuesta de Randall a continuación es correcta: ¿puede marcarlo así para futuros visitantes?
Bill
1

NUI es una alternativa al proxy UIAppearance. Le da control sobre la fuente (y muchos otros atributos) de una gran cantidad de tipos de elementos de la interfaz de usuario en toda su aplicación simplemente modificando una hoja de estilo, que puede reutilizarse en múltiples aplicaciones.

Después de agregar una NUILabelclase a sus etiquetas, puede controlar fácilmente su fuente en la hoja de estilo:

LabelFontName    String    Helvetica

Si tiene etiquetas con diferentes tamaños de fuente, puede controlar sus tamaños usando las clases Label, LargeLabel y SmallLabel de NUI, o incluso crear rápidamente sus propias clases.

Tom
fuente
1

Estoy usando este tipo de clase de fuente en Swift. Usando la clase de extensión de fuente.

enum FontName: String {

  case regular      = "Roboto-Regular"

}

//MARK: - Set Font Size
enum FontSize: CGFloat {
    case size = 10

}
extension UIFont {

    //MARK: - Bold Font
  class var regularFont10: UIFont {
        return UIFont(name: FontName.regular.rawValue, size:FontSize.size.rawValue )!
    }
}
Karthickkck
fuente
0

Para Xamarin.iOS dentro del FinishedLaunching()código de colocación de AppDelegate como este: -

UILabel.Appearance.Font= UIFont.FromName("Lato-Regular", 14);

establezca la fuente para toda la aplicación y agregue la UIAppFontstecla ' ' en Info.plist, la ruta debe ser la ruta donde se encuentra su archivo de fuente .ttf. Para mí estaba dentro de la carpeta 'fuentes' en mi proyecto.

<key>UIAppFonts</key>
    <array>
        <string>fonts/Lato-Regular.ttf</string>
    </array>
Annu
fuente
0

Como @Randall mencionó, el UIApperanceproxy iOS 5.0+ se puede usar para personalizar la apariencia de todas las instancias de una clase. Leer más .

La función de autocompletar de Xcodes no muestra todas las propiedades disponibles y puede generar un error, pero puede escribirlo y se compilará.

UILabel.apperance().font = UIFont.systemFont(ofSize: 17, weight: .regular)
esesmuedgars
fuente
-1

Logramos 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.redColor()
        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)
        }
    }    

Haga controladores de vista para niños y asócielos con un StoryBoard VC, agregue textLabel.

    import UIKit

    class FontTestController: ParentViewController {
        @IBOutlet var testLabel: UILabel!

        override func viewDidLoad() {
            super.viewDidLoad()
            testLabel.font =  appFont
            testLabel.textColor = appUIColor
        }

O haga una clase UILabel personalizada (método de subclasificación) y asóciele las etiquetas requeridas.

import Foundation
import UIKit

class CustomFontLabel: UILabel {
    required 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 alterar las propiedades de uilabel / cualquier vista todos juntos en algunos cambios simples en Parent VC.

2) 'para' bucle UIView para sub vistas. Funciona solo en un VC 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)    
                }               
            }       
        }
AG
fuente