Festlegen einer Standardschriftart für die gesamte iOS-App?

155

Ich habe eine benutzerdefinierte Schriftart, die ich für alles verwenden möchte, was Text in meiner App, Beschriftungen, Textansichten usw. anzeigt.

Gibt es eine Möglichkeit, die Standardschriftart (Beschriftungen verwenden standardmäßig SystemFont) für die gesamte App festzulegen?

Sam Jarman
quelle
7
Ich habe mich massiv mit diesem Leid befasst. Wir haben ehrlich gesagt festgestellt, dass es am einfachsten ist, für jedes Steuerelement eine (triviale) neue Klasse zu erstellen. Machen Sie also für UIButton SJButton. Vergessen Sie nicht, sowohl initWithFrame als auch initWithCode zu überschreiben. Stellen Sie für jedes Steuerelement (z. B. UIButton usw.) die Farben oder was auch immer Sie möchten ein. Nehmen Sie die Größe (dh die Größe, die auf dem Storyboard festgelegt ist) im Int-Code sorgfältig auf und verwenden Sie dann (wie Sie es bevorzugen) diese Größe (und legen Sie beispielsweise die Schriftart und Farbe fest - was auch immer). Es sind nur ein paar Codezeilen, es ist unglaublich aufgeräumt und spart Ihnen auf lange Sicht viel Zeit.
Fattie
@JoeBlow Vielen Dank, dass Sie Ihre Ergebnisse veröffentlicht haben - ich wollte gerade Zeit damit verbringen, diese selbst zu beantworten
jj.
@ jj- Richtig. Vergiss auch nicht, dass du IBDesignablediese Tage unbedingt benutzen musst . Ich hoffe es hilft. Beachten Sie
Fattie

Antworten:

158

In iOS 5 scheint die Verwendung des UIAppearance-Proxys möglich zu sein.

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

Dadurch wird die Schriftart so eingestellt, wie es Ihre benutzerdefinierte Schriftart für alle UILabels in Ihrer App ist. Sie müssen es für jedes Steuerelement (UIButton, UILabel usw.) wiederholen.

Denken Sie daran, dass Sie den UIAppFonts-Wert in Ihre info.plist einfügen und den Namen der Schriftart angeben müssen, die Sie einschließen.

Randall
quelle
46
Danke für die Antwort. Ich konnte das zum Laufen bringen. Wissen Sie, ob es eine Möglichkeit gibt, die Schriftart ohne Angabe der Schriftgröße anzugeben? Ich habe Beschriftungen in meiner App, die nicht dieselbe Schriftgröße haben.
Brandon
23
Kann ich dies tun, ohne die Punktgröße jeder Instanz zu überschreiben?
Michael Forrest
17
setFont:Methode ist veraltet
Anand
12
@Anand bist du dir da sicher? Ich sehe es nicht als veraltet in UILabel. Es ist veraltet, UIButtonaber es wird stattdessen die Schriftart für die titleLabelEigenschaft verwendet, die a ist. UILabelDaher UILabelsollte es in Ordnung sein , nur die Schriftart mit dem Erscheinungs-Proxy für festzulegen.
Adrian Schönig
6
@Anand es ist für UILabel nicht veraltet.
Alastair Stuart
118

Swift 5

Basierend auf der Antwort von Fábio Oliveira ( https://stackoverflow.com/a/23042694/2082851 ) mache ich meine eigene schnelle 4.

Kurz gesagt, diese Erweiterung tauschen Standardfunktionen init(coder:), systemFont(ofSize:), boldSystemFont(ofSize:), italicSystemFont(ofSize:)mit meinen benutzerdefinierten Methoden.

Beachten Sie, dass es nicht vollständig implementiert ist, aber Sie können weitere Methoden basierend auf meiner Implementierung austauschen.

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
quelle
2
beste Antwort!! Automatische Überschreibung der Systemschrift, brillant
Kappe
2
Wenn jemand Probleme mit der Zeile "NSCTFontUIUsageAttribute" hat: if let fontAttribute = fontDescriptor.fontAttributes[.nsctFontUIUsage] as? String {hat den Trick für mich getan.
Wissen
1
scheint nicht mit UILabels zu funktionieren, die den Textstil festlegen (Fettdruck, Überschrift, Titel usw.) ... funktioniert nur mit Schriftarten, für die eine bestimmte Größe und Systemschriftart festgelegt ist. @ nahung89
aviran
1
Dadurch werden auch einige System-UI-Schriftarten umgeschaltet. Zum Beispiel die Tastaturvorschlagsliste und das Aktionsblatt. Ich weiß nicht, ob dies dazu führt, dass Apple die App ablehnt
Henry H Miao
1
Es ist ein Jahr her, seit diese Antwort veröffentlicht wurde. Hat jemand einen "nativeren" Apple-Weg, um dies zu erreichen?
Greg Hilston
75

Es gibt auch eine andere Lösung, die darin besteht, systemFont zu überschreiben.

Erstellen Sie einfach eine Kategorie

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

Dies ersetzt die Standardimplementierung und die meisten UIControls verwenden systemFont.

Hugues BR
quelle
1
Liegt dies innerhalb der Apple-Richtlinien?
Rambatino
Es ist eher ein Hack. Ich habe mein App-Register bei diesem Hack nicht hinzugefügt, da keine privaten Methoden verwendet werden. Wenn Sie eine robustere Lösung wünschen, empfehle ich Ihnen auch, dies zu überprüfen: github.com/0xced/FontReplacer
Hugues BR
2
Das ist in Ordnung. Apple möchte nur nicht, dass Sie undokumentierte Funktionen verwenden. Sie dürfen öffentliche Methoden "swizzeln".
mxcl
4
Wenn eine Kategorie Methoden mit derselben Signatur wie die Klasse hat, die sie erweitert, ist das Verhalten undefiniert. Um Klassenmethoden zu ersetzen, sollten Sie Methoden-Swizzling verwenden (was ebenfalls keine gute Idee ist).
GreatWiz
1
Wie andere bereits betont haben, führt diese Lösung, obwohl sie wahrscheinlich die meiste Zeit wirksam ist, technisch das Potenzial für undefiniertes Verhalten ein. Wenn Sie kein Risiko eingehen möchten, ist das Methoden-Swizzling möglicherweise die bessere Option. Die Antwort hier bietet die gleiche Lösung per Swizzling: stackoverflow.com/questions/19542942/…
Nathan Hosselton
63

Wenn Sie Swift verwenden, können Sie eine UILabel-Erweiterung erstellen:

extension UILabel {

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

}

Und dann, wo Sie Ihren Auftritt als Stellvertreter machen:

UILabel.appearance().substituteFontName = applicationFont

Es gibt einen äquivalenten Objective-C-Code, der UI_APPEARANCE_SELECTORfür eine Eigenschaft mit dem Namen verwendet wird substituteFontName.

Zusatz

Für den Fall, dass Sie fett gedruckte und reguläre Schriftarten separat festlegen möchten:

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

Dann für Ihre UIAppearance-Proxys:

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

Hinweis: Wenn Sie feststellen, dass die fettgedruckte Ersetzung nicht funktioniert, enthält der Standardschriftname möglicherweise nicht "Mittel". Schalten Sie diese Zeichenfolge nach Bedarf für ein anderes Spiel aus (danke an Mason in den Kommentaren unten).

Sandy Chapman
quelle
Ein Nachteil, den ich festgestellt habe, ist, dass beim Initiieren von Warnungen mit UIAlertController die Schaltfläche mit dem Stil .Cancel mit der Schaltfläche mit dem Stil .Default identisch ist (zumindest bei Verwendung von GillSans). Während normalerweise .Cancel eine Schriftart mit normaler Gewichtung ist und .Default fett gedruckt ist. Irgendwelche Ideen?
Mason G. Zhwiti
Entschuldigung, ich meinte. Abbrechen von Etiketten wäre normalerweise fett und Standard wäre normalerweise normales Gewicht.
Mason G. Zhwiti
2
@ MasonG.Zhwiti In diesem Fall würde ich die UILabelErweiterung wahrscheinlich so einrichten , dass ein zusätzlicher Schriftname für Fettdruck verwendet wird. setÜberprüfen Sie dann im Do, ob "Bold" im Schriftnamen enthalten ist, ignorieren Sie das Set in einem Fall und verwenden Sie es in dem anderen. Ich werde ein Beispiel bearbeiten und hinzufügen.
Sandy Chapman
@ SandyChapman Danke! Ich probiere diese neue Technik aus und sie macht Sinn, aber sie scheint für mich nicht zu funktionieren. Ich verwende GillSans und GillSans-Bold auf dem iOS 8.3-Simulator. Haben Sie diese Technik getestet?
Mason G. Zhwiti
2
@ SandyChapman Ich habe herausgefunden, was los ist. Die Standardschriftarten für iOS 8 sind in der Regel entweder HelveticaNeueInterface-Regular oder (fett) HelveticaNeueInterface-MediumP4. Die Suche nach "Bold" war also nie passend. Ich habe es geändert rangeOfString("Medium")und es hat funktioniert.
Mason G. Zhwiti
23

Aus der Antwort von Hugues BR entwickelt, aber mithilfe der Methode Swizzling bin ich zu einer Lösung gekommen, bei der alle Schriftarten in meiner App erfolgreich in eine gewünschte Schriftart geändert werden.

Ein Ansatz mit Dynamic Type sollte das sein, wonach Sie unter iOS 7 suchen sollten. Die folgende Lösung verwendet Dynamic Type nicht.


Anmerkungen:

  • Der unten stehende Code wurde in seinem vorliegenden Zustand nie der Apple-Genehmigung unterzogen.
  • Es gibt eine kürzere Version davon, die die Apple-Übermittlung bestanden hat, dh ohne - initWithCoder:Überschreibung. Dies wird jedoch nicht alle Fälle abdecken.
  • Der folgende Code ist in einer Klasse vorhanden, mit der ich den Stil meiner App festlege, der in meiner AppDelegate-Klasse enthalten ist und somit überall und für alle UIFont-Instanzen verfügbar ist.
  • Ich verwende Zapfino hier nur, um die Änderungen besser sichtbar zu machen.
  • Jede Verbesserung dieses Codes ist willkommen.

Diese Lösung verwendet zwei verschiedene Methoden, um das Endergebnis zu erzielen. Die erste besteht darin, die UIFont-Klassenmethoden + systemFontWithSize:und ähnliche Methoden mit denen zu überschreiben , die meine Alternativen verwenden (hier verwende ich "Zapfino", um keine Zweifel daran zu lassen, dass die Ersetzung erfolgreich war).

Die andere Methode besteht darin, die - initWithCoder:Methode in UIFont zu überschreiben, um das Auftreten CTFontRegularUsageund Ähnliches meiner Alternativen zu ersetzen . Diese letzte Methode war notwendig, da ich festgestellt habe, dass UILabelin NIB-Dateien codierte Objekte die + systemFontWithSize:Methoden nicht überprüfen , um ihre Systemschrift zu erhalten, und sie stattdessen als UICTFontDescriptorObjekte codieren . Ich habe versucht zu überschreiben, - awakeAfterUsingCoder:aber irgendwie wurde es für jedes verschlüsselte Objekt in meinem Storyboard aufgerufen und verursachte Abstürze. Das Überschreiben - awakeFromNibwürde mir nicht erlauben, das NSCoderObjekt zu lesen .

#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
quelle
Wie Sie diese Implementierung auf iOS6 verwenden, die UIFontDescriptor nicht haben
Utku Yıldırım
Ich habe den Decoderschlüssel "UIFontTraits" verwendet, um zu überprüfen, ob die angegebene Schrift fett oder kursiv ist, und sie durch meine eigenen Variationen zu ersetzen. Habe es von diesem Kern hier bekommen gist.github.com/Daij-Djan/5046612 .
Fábio Oliveira
Vielen Dank für die Antwort. Ich habe vorerst eine andere Lösung verwendet. Ich werde es überprüfen, wenn ich es wieder brauche :)
Utku Yıldırım
2
danke @ FábioOliveira, es funktioniert wie ein Zauber! Nur noch eine Sache, die Sie brauchen, um #import <objc / runtime.h> in den Header zu setzen, sonst erhalten Sie Fehler, wenn Sie die '
Method'
Aus irgendeinem Grund UIAlertControllerändern modals ( ) unter iOS 8 die Schriftart nicht.
Randomblue
13

Um die Antwort von Sandy Chapman zu vervollständigen , finden Sie hier eine Lösung in Ziel-C (platzieren Sie diese Kategorie an einer beliebigen Stelle, an der Sie sie ändern möchten UILabel Appearance):

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

In der Schnittstellendatei sollte diese Methode öffentlich deklariert sein, damit sie später von Orten wie Ihrem App-Delegaten verwendet werden kann:

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

Dann können Sie das ändern Appearancemit:

[[UILabel appearance] setSubstituteFontName:@"SourceSansPro-Light"];
Damien Debin
quelle
1
Hallo, meinst du "irgendwo", dieser Code müsste in jedem View-Controller hinzugefügt werden und muss jedes UILabel im Controller verwendet werden, in dem du die Schriftart ändern möchtest?
Jules
Nein, Sie müssen diesen Code einmal und überall in Ihrem Projekt einfügen . in Ihrem appdelegate zum Beispiel.
Damien Debin
1
@DamienDebin Ich möchte Fettdruck für Fettdruck verwenden, aber dies ändert Fettdruck in Licht. Irgendwo herum?
Zeeshan
Eigentlich funktioniert es, aber sollte es "Kategorie" oder "Erweiterung" sein? Der Unterschied hier erklärt: stackoverflow.com/questions/7136124/…
Darius Miliauskas
4

KOMMENTAR FÜR SWIFT 3.0 UND SWIFT WARNUNG

Sie können die Warnmeldung in der folgenden Zeile entfernen:

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

Durch Ersetzen durch:

let initCoderMethod = class_getInstanceMethod(self, #selector(UIFontDescriptor.init(coder:)))
ucotta
quelle
Lol. Ich wusste nicht, dass Swift dies zulässt. Übrigens werde ich es auf die obige Antwort aktualisieren. Danke @ucotta!
nahung89
4

Für Swift 5

Alle oben genannten Antworten sind korrekt, aber ich habe es auf wenig andere Weise getan, je nach Gerätegröße . Hier in der ATFontManager-Klasse habe ich die Standardschriftgröße festgelegt, die oben in der Klasse als defaultFontSize definiert wird. Dies ist die Schriftgröße von iphone plus und Sie können sie gemäß Ihren Anforderungen ändern.

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

Ich habe einen bestimmten Schriftnamen hinzugefügt. Weitere Informationen finden Sie hier.

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

Diese Klasse bezieht sich auf den Gerätedetektor, um je nach Gerät eine geeignete Schriftgröße bereitzustellen.

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

Wie benutzt man. Hoffe es wird helfen.

//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
quelle
3

Keine dieser Lösungen funktioniert universell in der gesamten App. Eine Sache, die ich beim Verwalten der Schriftarten in Xcode gefunden habe, ist das Öffnen des Storyboards als Quellcode (Klicken Sie bei gedrückter Ctrl-Taste auf das Storyboard im Datei-Navigator> "Öffnen als"> "Quelle") und das anschließende Suchen und Ersetzen.

Gingi
quelle
3

Die Schriftart muss immer in Code und Feder / Storyboard festgelegt werden.

Für den Code, genau wie Hugues BR sagte , kann dies in der Kategorie das Problem lösen.

Für die Feder / das Storyboard können wir awizzFromNib mit Swizzling ändern, um den Schrifttyp zu ändern, da das UI-Element von der Feder / dem Storyboard es immer aufruft, bevor es auf dem Bildschirm angezeigt wird.

Ich nehme an, Sie kennen Aspekte. Es ist eine Bibliothek für die AOP-Programmierung, die auf Method Swizzling basiert. Wir erstellen eine Kategorie für UILabel, UIButton, UITextView, um sie zu implementieren.

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

Das ist alles, Sie können HelveticaNeue-light in ein Makro mit Ihrem Schriftnamen ändern.

Peng Xiaofeng
quelle
3

Ich habe meine eigene Konvertierung der Typografie für Swift 4 erstellt, nachdem ich einige Beiträge überprüft habe. Sie deckt die meisten Fälle ab, z.

1. Fügen Sie der Projektstruktur und der .plist-Datei (mit demselben Namen) Schriftarten hinzu:

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

Dann

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

Rufen Sie zum Schluss die erstellte Methode Appdelegatewie folgt auf:

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

        UIFont.overrideDefaultTypography()
        return true
    }
}
Javier Amor Penas
quelle
@sheshnath kannst du uns mehr Absturzinformationen geben?
Javier Amor Penas
1
Entschuldigung, Fehler war von meiner Seite, Schrift wurde nicht in info.plist aufgeführt
shesh nath
@midhunp Könnten Sie expliziter sein, damit es bei Ihnen nicht funktioniert?. Es funktioniert gut für mich mit fetter Schrift.
Javier Amor Penas
2

Wahrscheinlich nicht, wahrscheinlich haben Sie die Schriftart selbst in Ihrem Steuerelement festgelegt, aber Sie können den Vorgang vereinfachen, indem Sie zentralisieren, woher Sie die Schriftarten beziehen. Lassen Sie beispielsweise den App-Delegaten oder eine andere allgemeine Klasse eine Methode haben, die die zurückgibt Schriftart und alles, was zum Festlegen der Schriftart benötigt wird, kann diese Methode aufrufen. Dies hilft, wenn Sie Ihre Schriftart ändern müssen. Sie müssen sie an einer Stelle ändern und nicht überall, wo Sie die Schriftarten festlegen. Eine andere Alternative kann darin bestehen, Unterklassen von zu erstellen Ihre UI-Elemente, die die Schriftart automatisch festlegen, aber möglicherweise übertrieben sind.

Daniel
quelle
Für die Aufzeichnung ist dies, was ich getan habe, aber @Randall brauchte den Repräsentanten und gab eine gute Antwort. Ich muss nur weniger als 5.0 unterstützen
Sam Jarman
4
Ich bin nicht einverstanden mit dem, was du getan hast. Die von Ihnen ausgewählte Antwort ist ungültig, wenn Ihre Frage mit iphone-sdk-4.0 gekennzeichnet ist.
Paulo Casaretto
@ Sam Jarman, Randalls Antwort unten ist richtig - können Sie es für zukünftige Besucher so markieren?
Bill
1

NUI ist eine Alternative zum UIAppearance-Proxy. Sie können die Schriftart (und viele andere Attribute) einer großen Anzahl von UI-Elementtypen in Ihrer Anwendung steuern, indem Sie einfach ein Stylesheet ändern, das für mehrere Anwendungen wiederverwendet werden kann.

Nachdem NUILabelSie Ihren Beschriftungen eine Klasse hinzugefügt haben , können Sie deren Schriftart im Stylesheet leicht steuern:

LabelFontName    String    Helvetica

Wenn Sie Beschriftungen mit unterschiedlichen Schriftgrößen haben, können Sie deren Größe mithilfe der NUI-Klassen Label, LargeLabel und SmallLabel steuern oder sogar schnell eigene Klassen erstellen.

Tom
quelle
1

Ich benutze wie diese Art von Schriftklasse in Swift. Verwenden der Font-Erweiterungsklasse.

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

Für Xamarin.iOS in AppDelegates FinishedLaunching()Put-Code wie folgt : -

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

UIAppFontsLegen Sie die Schriftart für die gesamte Anwendung fest und fügen Sie in der Info.plist den Schlüssel ' ' hinzu. Der Pfad sollte der Pfad sein, in dem sich Ihre Schriftartdatei .ttf befindet. Für mich befand sie sich in meinem Projekt im Ordner 'fonts'.

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

Wie @Randall erwähnt iOS 5.0+ UIApperanceProxy kann das Aussehen aller Instanzen einer Klasse anpassen verwendet werden , lesen Sie mehr .

Die automatische Vervollständigung von Xcodes zeigt nicht alle verfügbaren Eigenschaften an und kann einen Fehler auslösen. Sie können ihn jedoch einfach eingeben und er wird kompiliert.

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

Dasselbe haben wir in Swift-Xcode 7.2 mit Parent View Controller und Child View Controller (Inheritance) erreicht.

Datei - Neu - Cocoa Touch-Klasse - 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)
        }
    }    

Erstellen Sie untergeordnete Ansichtscontroller und verknüpfen Sie sie mit einem StoryBoard VC. Fügen Sie ein textLabel hinzu.

    import UIKit

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

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

ODER Erstellen Sie eine benutzerdefinierte UILabel-Klasse (Subklassifizierungsmethode) und ordnen Sie ihr die erforderlichen Beschriftungen zu.

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

Hinweis: Die in Parent VC deklarierte Schriftart und Farbe sind in CustomFontLabel implementiert. Der Vorteil ist, dass wir die Eigenschaften von uilabel / any view zusammen in einigen einfachen Änderungen in Parent VC ändern können.

2) 'for' Schleife UIView für Unteransichten. Es funktioniert nur auf einem bestimmten VC.

    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
quelle