Impostare un carattere predefinito per l'intera app iOS?


155

Ho un carattere personalizzato che voglio usare per tutto ciò che mostra testo nella mia app, etichette, visualizzazioni di testo ecc.

C'è un modo per impostare il carattere predefinito (le etichette per impostazione predefinita utilizzano SystemFont) per l'intera app?


7
Avendo guardato in massa a questo guaio. Onestamente abbiamo scoperto che la cosa più semplice da fare è creare una (banale) nuova classe, per ogni controllo. Quindi per UIButton, crea SJButton. Non dimenticare di sostituire sia initWithFrame che initWithCode. Per ogni controllo (ad esempio UIButton, ecc.) Imposta i colori o quello che preferisci. Raccogli attentamente dica la dimensione (cioè quella sarà la dimensione IMPOSTATA SULLA STORYBOARD) nel codice int, quindi (come preferisci) usa quella dimensione (e imposta, diciamo, il carattere, il colore - qualunque cosa). È solo poche righe di codice, è incredibilmente ordinato e ti fa risparmiare molto tempo nel lungo periodo.
Fattie,

@JoeBlow Grazie per aver pubblicato le tue scoperte - stava per passare il tempo a cercare di rispondere da solo
jj.

@ jj- Giusto. Non dimenticare anche che DEVI sicuramente usare IBDesignablequesti giorni. Spero che sia d'aiuto. Considera anche questo QA interessante: stackoverflow.com/a/38000466/294884
Fattie

Risposte:


158

Sembra essere possibile in iOS 5 utilizzando il proxy UIAppearance.

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

Ciò imposterà il carattere in modo che sia qualunque sia il tuo carattere personalizzato per tutti gli UILabels nella tua app. Dovrai ripeterlo per ogni controllo (UIButton, UILabel, ecc.).

Ricorda che dovrai inserire il valore UIAppFonts nel tuo info.plist e includere il nome del carattere che stai includendo.


46
Grazie per la risposta. Sono stato in grado di farlo funzionare. Sai se esiste un modo per specificare il carattere senza specificare la dimensione del carattere? Nella mia app sono presenti etichette che non condividono la stessa dimensione del carattere.
Brandon,

23
Posso farlo senza sovrascrivere la dimensione in punti di ogni istanza?
Michael Forrest,

17
setFont:il metodo è obsoleto
Anand

12
@Anand sei sicuro di questo? Non lo vedo contrassegnato come deprecato in UILabel. È deprecato per UIButtonma utilizza invece il carattere per la titleLabelproprietà che è a UILabel, quindi basta impostare il carattere con il proxy aspetto per UILabeldovrebbe andare bene.
Adrian Schönig,

6
@Anand non è deprecato per UILabel.
Alastair Stuart

118

Swift 5

Basati sulla risposta di Fábio Oliveira ( https://stackoverflow.com/a/23042694/2082851 ), realizzo il mio rapido 4.

In breve, questo funzioni scambi estensione di default init(coder:), systemFont(ofSize:), boldSystemFont(ofSize:),italicSystemFont(ofSize:) con i miei metodi personalizzati.

Si noti che non è completamente implementato, ma è possibile scambiare più metodi in base alla mia implementazione.

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

2
migliore risposta!! sovrascrive automaticamente il font di sistema, brillante
Kappe

2
Se qualcuno ha problemi con la linea "NSCTFontUIUsageAttribute": ha if let fontAttribute = fontDescriptor.fontAttributes[.nsctFontUIUsage] as? String {fatto il trucco per me.
Conoscenza

1
sembra non funzionare con UILabels che impostano lo stile di testo (grassetto, titolo, titolo, ecc.) ... funziona solo con caratteri che hanno una dimensione specifica e un set di caratteri di sistema. @ nahung89
aviran,

1
Questo cambia anche alcuni caratteri dell'interfaccia utente del sistema. Ad esempio, l'elenco dei suggerimenti della tastiera e il foglio delle azioni. Non so se questo causerà il rifiuto dell'app da parte di Apple
Henry H Miao,

1
È passato un anno da quando questa risposta è stata pubblicata. Qualcuno ha un modo Apple "nativo" per raggiungere questo obiettivo?
Greg Hilston,

75

C'è anche un'altra soluzione che sarà quella di sovrascrivere systemFont.

Basta creare una categoria

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

Ciò sostituirà l'implementazione predefinita e la maggior parte degli UIControls utilizza systemFont.


1
È all'interno delle linee guida Apple?
Rambatino,

È più un trucco. Non ho aggiunto il mio registro delle app con questo trucco, poiché non utilizza alcun metodo privato. Se vuoi una soluzione più solida, ti suggerisco anche di controllare questo: github.com/0xced/FontReplacer
Hugues BR

2
Questo va bene. Apple non vuole che tu usi funzioni non documentate. Hai il permesso di "swizzle" metodi che sono pubblici.
mxcl,

4
Quando una categoria ha metodi con la stessa firma della classe che si sta estendendo, il comportamento non è definito. Per sostituire i metodi di classe dovresti usare il metodo swizzling (che non è una buona idea).
GreatWiz,

1
Come altri hanno sottolineato, questa soluzione, sebbene sia probabilmente efficace per la maggior parte del tempo, sta tecnicamente introducendo il potenziale per un comportamento indefinito. Se non hai voglia di rischiare, il metodo che sfrigola potrebbe essere un'opzione migliore. La risposta qui fornisce la stessa soluzione tramite swizzling: stackoverflow.com/questions/19542942/...
Nathan Hosselton

64

Se stai usando Swift, puoi creare un'estensione UILabel:

extension UILabel {

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

}

E poi dove fai il tuo aspetto, procedi:

UILabel.appearance().substituteFontName = applicationFont

Esiste un codice Objective-C equivalente che utilizza UI_APPEARANCE_SELECTORuna proprietà con il nome substituteFontName.

aggiunta

Nel caso in cui desideri impostare caratteri grassetto e regolari separatamente:

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)
            }
        }
    }
}

Quindi per i tuoi proxy UIAppearance:

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

Nota: se stai scoprendo che la sostituzione in grassetto non funziona, è possibile che il nome del carattere predefinito non contenga "Medio". Cambia quella stringa per un'altra partita secondo necessità (grazie a Mason nei commenti qui sotto).


Uno svantaggio di ciò che ho scoperto è che quando avvio avvisi con UIAlertController, il pulsante con lo stile .Cancel è lo stesso del pulsante con lo stile .Default (almeno quando si utilizza GillSans). Considerando che normalmente .Cancel sarebbe un carattere di peso normale e .Default sarebbe in grassetto. Qualche idea?
Mason G. Zhwiti,

Siamo spiacenti, intendevo dire. Le etichette di annullamento sarebbero normalmente in grassetto e l'impostazione predefinita avrebbe un peso normale.
Mason G. Zhwiti,

2
@ MasonG.Zhwiti In quel caso, probabilmente avrei impostato l' UILabelestensione per prendere un nome di carattere aggiuntivo in grassetto. Quindi, setfai un controllo per vedere se "Grassetto" è nel nome del font e ignora il set in un caso e usalo nell'altro. Modificherò e aggiungerò un esempio.
Sandy Chapman

@SandyChapman Grazie! Sto provando questa nuova tecnica, e ha senso, ma non sembra funzionare per me. Sto usando GillSans e GillSans-Bold sul simulatore iOS 8.3. Hai provato questa tecnica?
Mason G. Zhwiti,

2
@SandyChapman Ho capito cosa sta succedendo. I caratteri predefiniti per iOS 8 tendono ad essere HelveticaNeueInterface-Regular o (per grassetto) HelveticaNeueInterface-MediumP4. Quindi cercare "grassetto" non ha mai eguagliato nulla. L'ho cambiato rangeOfString("Medium")e ha funzionato.
Mason G. Zhwiti,

23

Sviluppando dalla risposta Hugues BR ma usando il metodo swizzling, sono arrivato a una soluzione che sta cambiando con successo tutti i caratteri nel carattere desiderato nella mia app.

Un approccio con Dynamic Type dovrebbe essere quello che dovresti cercare su iOS 7. La seguente soluzione non sta usando Dynamic Type.


Appunti:

  • il codice seguente, nello stato presentato, non è mai stato sottoposto all'approvazione di Apple;
  • esiste una versione più breve di essa che ha superato l'invio di Apple, ovvero senza - initWithCoder: override. Tuttavia, ciò non coprirà tutti i casi;
  • il seguente codice è presente in una classe che uso per impostare lo stile della mia app, che è inclusa dalla mia classe AppDelegate, quindi disponibile ovunque e in tutte le istanze di UIFont;
  • Sto usando Zapfino qui solo per rendere le modifiche molto più visibili;
  • qualsiasi miglioramento che potresti trovare in questo codice è il benvenuto.

Questa soluzione utilizza due metodi diversi per ottenere il risultato finale. Il primo è sovrascrivere i metodi della classe UIFont+ systemFontWithSize: e simili con quelli che usano le mie alternative (qui uso "Zapfino" per non lasciare dubbi sul fatto che la sostituzione abbia avuto successo).

L'altro metodo è quello di sovrascrivere il - initWithCoder:metodo su UIFont per sostituire qualsiasi occorrenza CTFontRegularUsagee simili con le mie alternative. Quest'ultimo metodo era necessario perché ho scoperto che gli UILabeloggetti codificati nei file NIB non controllano i + systemFontWithSize:metodi per ottenere il loro carattere di sistema e invece li codificano come UICTFontDescriptoroggetti. Ho provato a scavalcare - awakeAfterUsingCoder:ma in qualche modo veniva chiamato per ogni oggetto codificato nel mio storyboard e causava arresti anomali. L'override - awakeFromNibnon mi consentirebbe di leggere l' NSCoderoggetto.

#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

Come usi questa implementazione su iOS6 che non ha UIFontDescriptor
Utku Yıldırım

Ho usato il tasto del decodificatore "UIFontTraits" per verificare se il carattere fornito è grassetto o corsivo e sostituirlo con le mie varianti. Capito da questa idea qui gist.github.com/Daij-Djan/5046612 .
Fábio Oliveira,

Grazie per la risposta ho usato un'altra soluzione per ora. Lo controllerò quando ne avrò più bisogno :)
Utku Yıldırım

2
grazie @ FábioOliveira, funziona come un fascino! Ancora un'altra cosa che devi mettere #import <objc / runtime.h> nell'intestazione, altrimenti otterrai un errore usando la classe 'Method' (errore che ottengo in XCode 6)
nahung89

Per qualche ragione, su iOS 8, modals ( UIAlertController) non cambia carattere.
Randomblue,

13

Per completare la risposta di Sandy Chapman , ecco una soluzione in Objective-C (metti questa categoria ovunque tu voglia cambiare UILabel Appearance):

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

Il file di interfaccia dovrebbe avere questo metodo dichiarato pubblicamente per essere utilizzato successivamente da luoghi come il tuo delegato dell'app:

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

Quindi, puoi modificare il Appearancecon:

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

1
Ciao, vuoi dire "ovunque", quel codice dovrebbe essere aggiunto in ogni controller di visualizzazione e avere ogni UILabel utilizzato nel controller, dove desideri cambiare il carattere?
Jules,

No, devi inserire questo codice una volta , ovunque nel tuo progetto; nel tuo delegato dell'app, ad esempio.
Damien Debin,

1
@DamienDebin Voglio usare il carattere grassetto per grassetto ma questo cambia in grassetto alla luce. Qualche modo?
Zeeshan,

In realtà, funziona, ma dovrebbe essere "Categoria" o "Estensione"? La differenza spiegata qui: stackoverflow.com/questions/7136124/...
Darius Miliauskas

4

COMMENTO PER SWIFT 3.0 E SWIFT ATTENZIONE

È possibile rimuovere il messaggio di avviso in linea:

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

Sostituendolo con:

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

Lol. Non sapevo che Swift permettesse di usarlo. A proposito, lo aggiornerò alla risposta sopra. Grazie @ucotta!
nahung89,

4

Per Swift 5

Tutte le risposte di cui sopra sono corrette ma ho fatto in modo leggermente diverso in base alle dimensioni del dispositivo . Qui, nella classe ATFontManager, ho impostato la dimensione del carattere predefinita che è definita nella parte superiore della classe come defaultFontSize , questa è la dimensione del carattere di iPhone Plus e puoi cambiarla in base alle tue esigenze.

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)!
        }
    }
}
     

Ho aggiunto un determinato nome di carattere, per di più puoi aggiungere il nome del carattere e digitare qui.

   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"
    }

Questa classe si riferisce al rilevatore di dispositivi al fine di fornire la dimensione del carattere appropriata in base al 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
        }
    }
}

Come usare. Spero che possa aiutare.

//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)

3

Nessuna di queste soluzioni funziona universalmente in tutta l'app. Una cosa che ho trovato utile per gestire i caratteri in Xcode è aprire lo Storyboard come codice sorgente (Control-click storyboard in Navigatore file> "Apri come"> "Sorgente"), quindi fare un trova e sostituisci.


3

Il tipo di carattere deve essere sempre impostato in codice e pennino / storyboard.

Per il codice, proprio come ha detto Hugues BR , farlo in catagoria può risolvere il problema.

Per il pennino / storyboard, possiamo Metodo Swizzling awakeFromNib per cambiare il tipo di carattere poiché l'elemento UI dal pennino / storyboard lo chiama sempre prima di mostrarlo sullo schermo.

Suppongo che tu sappia Aspetti . È una libreria per la programmazione AOP, basata su Method Swizzling. Creiamo catagoria per UILabel, UIButton, UITextView per 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

Questo è tutto, puoi cambiare HelveticaNeue-light in una macro con il nome del tuo font.


3

Ho creato la mia conversione della tipografia per Swift 4 dopo aver esaminato alcuni post, copre la maggior parte dei casi, come ad esempio:

1 ° Aggiungi i caratteri per estrarre il progetto e al file .plist (con lo stesso nome):

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

Poi

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)
        }
    }
}

Infine chiama il metodo creato Appdelegatecome il prossimo:

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

        UIFont.overrideDefaultTypography()
        return true
    }
}

@sheshnath puoi darci maggiori informazioni sugli arresti anomali?
Javier Amor Penas,

1
scusa errore era dalla mia parte, il font non era elencato in info.plist
shesh nath

@midhunp Potresti essere più esplicito in modo che non funzioni per te ?. Funziona bene per me con un carattere grassetto.
Javier Amor Penas,

2

Probabilmente no, avrai probabilmente impostato tu stesso il carattere sul tuo controllo, ma puoi semplificare il processo centralizzando da dove ottieni i tipi di carattere, ad esempio se il delegato dell'app o qualche altra classe comune ha un metodo che restituisce il font e qualsiasi cosa necessiti per impostare il font può chiamare quel metodo, che ti aiuterà nel caso in cui tu debba cambiare il font, lo cambi in un posto piuttosto che ovunque tu imposti i font ... Un'altra alternativa può essere quella di creare sottoclassi di elementi dell'interfaccia utente che imposteranno automaticamente il carattere, ma potrebbe essere eccessivo.


per la cronaca, questo è quello che ho fatto, ma @Randall aveva bisogno del rappresentante e ha fornito una buona risposta. Devo solo supportare meno di 5.0
Sam Jarman il

4
Non sono d'accordo con quello che hai fatto. La risposta che hai selezionato non è valida quando la tua domanda è taggata iphone-sdk-4.0.
Paulo Casaretto,

@ Sam Jarman, la risposta di Randall qui sotto è corretta: puoi contrassegnarla in questo modo per i futuri visitatori?
Bill

1

NUI è un'alternativa al proxy UIAppearance. Ti dà il controllo sul carattere (e molti altri attributi) di un gran numero di tipi di elementi dell'interfaccia utente in tutta l'applicazione, semplicemente modificando un foglio di stile, che può essere riutilizzato su più applicazioni.

Dopo aver aggiunto una NUILabelclasse alle etichette, puoi facilmente controllare il loro carattere nel foglio di stile:

LabelFontName    String    Helvetica

Se disponi di etichette con dimensioni di carattere diverse, puoi controllarne le dimensioni utilizzando le classi Etichetta, LargeLabel e SmallLabel di NUI o persino creare rapidamente le tue classi.


1

Sto usando come questo tipo di classe di caratteri in rapido. Utilizzando la classe di estensione dei caratteri.

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 )!
    }
}

0

Per Xamarin.iOS all'interno del FinishedLaunching()codice put di AppDelegate in questo modo: -

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

imposta font per l'intera applicazione e aggiungi il UIAppFontstasto ' ' su Info.plist, il percorso dovrebbe essere il percorso in cui si trova il tuo file di font .ttf. Per me era nella cartella 'fonts' nel mio progetto.

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

0

Come accennato @Randall iOS 5.0+ UIApperanceproxy può essere utilizzato per personalizzare l'aspetto di tutte le istanze di una classe per saperne di più .

Il completamento automatico di Xcodes non mostra tutte le proprietà disponibili e potrebbe generare un errore, ma puoi semplicemente digitarlo e verrà compilato.

UILabel.apperance().font = UIFont.systemFont(ofSize: 17, weight: .regular)

-1

Abbiamo ottenuto lo stesso risultato in Swift -Xcode 7.2 utilizzando Controller vista padre e Controller vista bambino (Ereditarietà).

File - Nuovo - Classe 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)
        }
    }    

Crea controller di visualizzazione figlio e associalo a un StoryBoard VC, aggiungi un textLabel.

    import UIKit

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

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

OPPURE Crea una classe UILabel personalizzata (metodo di classificazione secondaria) e associa ad essa le etichette richieste.

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: il carattere e il colore dichiarati in Parent VC sono implementati in CustomFontLabel. Il vantaggio è che possiamo modificare insieme le proprietà di uilabel / qualsiasi vista in alcune semplici modifiche in Parent VC.

2) "per" loop UIView per viste secondarie. Funziona solo su un VC particolare.

    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)    
                }               
            }       
        }
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.