为整个 iOS 应用设置默认字体?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/8707082/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-30 16:07:31  来源:igfitidea点击:

Set a default font for whole iOS app?

iosfonts

提问by Sam Jarman

I have a custom font I want to use for everything displaying text in my app, labels, text views etc.

我有一个自定义字体,我想用于在我的应用程序、标签、文本视图等中显示文本的所有内容。

Is there a way to set the default font (labels by default use SystemFont) for the whole app?

有没有办法为整个应用程序设置默认字体(标签默认使用 SystemFont)?

回答by Randall

It seems to be possible in iOS 5 using the UIAppearance proxy.

在 iOS 5 中使用 UIAppearance 代理似乎是可能的。

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

That will set the font to be whatever your custom font is for all UILabels in your app. You'll need to repeat it for each control (UIButton, UILabel, etc.).

这会将字体设置为应用程序中所有 UILabel 的自定义字体。您需要为每个控件(UIButton、UILabel 等)重复此操作。

Remember you'll need to put the UIAppFonts value in your info.plist and include the name of the font you're including.

请记住,您需要将 UIAppFonts 值放在 info.plist 中,并包含您要包含的字体的名称。

回答by nahung89

Swift 5

斯威夫特 5

Base on Fábio Oliveira's answer (https://stackoverflow.com/a/23042694/2082851), I make my own swift 4.

根据法比奥奥利维拉的回答(https://stackoverflow.com/a/23042694/2082851),我自己制作了 swift 4。

In short, this extension exchanges default functions init(coder:), systemFont(ofSize:), boldSystemFont(ofSize:), italicSystemFont(ofSize:)with my custom methods.

简而言之,这个扩展与我的自定义方法交换了默认函数init(coder:), systemFont(ofSize:), boldSystemFont(ofSize:), italicSystemFont(ofSize:)

Note that it's not fully implement, but you can exchange more methods base on my implementation.

请注意,它还没有完全实现,但您可以根据我的实现交换更多方法。

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

回答by Hugues BR

There is also another solution which will be to override systemFont.

还有另一种解决方案是覆盖 systemFont。

Just create a category

只需创建一个类别

UIFont+SystemFontOverride.h

UIFont+SystemFontOverride.h

#import <UIKit/UIKit.h>

@interface UIFont (SystemFontOverride)
@end

UIFont+SystemFontOverride.m

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

This will replace the default implementation and most UIControls use systemFont.

这将替换默认实现,并且大多数 UIControl 使用 systemFont。

回答by Sandy Chapman

If you're using Swift, you can create a UILabel extension:

如果你使用 Swift,你可以创建一个 UILabel 扩展:

extension UILabel {

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

}

And then where you do your appearance proxying:

然后你在哪里做你的外观代理:

UILabel.appearance().substituteFontName = applicationFont

There is equivalent Objective-C code using UI_APPEARANCE_SELECTORon a property with the name substituteFontName.

UI_APPEARANCE_SELECTOR在名称为 的属性上使用了等效的 Objective-C 代码substituteFontName

Addition

添加

For the case where you'd want to set bold and regular fonts separately:

对于您想要分别设置粗体和常规字体的情况:

extension UILabel {

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

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

Then for your UIAppearance proxies:

然后对于您的 UIAppearance 代理:

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

Note: if you're finding that the bold substitution isn't working, it's possible the default font name doesn't contain "Medium". Switch out that string for another match as needed (thanks to Mason in the comments below) .

注意:如果您发现粗体替换不起作用,则默认字体名称可能不包含“中”。根据需要切换出另一个匹配的字符串(感谢下面评论中的梅森)。

回答by Fábio Oliveira

Developing from Hugues BR answer but using method swizzling I've arrived to a solution that is successfully changing all the fonts to a desired font in my app.

从 Hugues BR 答案开发但使用方法 swizzling 我已经找到了一个解决方案,该解决方案成功地将我的应用程序中的所有字体更改为所需的字体。

An approach with Dynamic Type should be what you should look for on iOS 7. The following solution is not using Dynamic Type.

您应该在 iOS 7 上寻找动态类型的方法。以下解决方案不使用动态类型。



Notes:

笔记:

  • the code below, in its presented state, was never submitted to Apple approval;
  • there is a shorter version of it that passed Apple submission, that is without the - initWithCoder:override. However that won't cover all the cases;
  • the following code is present in a class I use to set the style of my app which is included by my AppDelegate class thus being available everywhere and to all UIFont instances;
  • I'm using Zapfino here just to make the changes much more visible;
  • any improvement you may find to this code is welcome.
  • 以下代码在其呈现状态下从未提交给 Apple 批准;
  • 有一个较短的版本通过了 Apple 提交,即没有- initWithCoder:覆盖。但是,这不会涵盖所有情况;
  • 以下代码出现在我用来设置应用程序样式的类中,该样式包含在我的 AppDelegate 类中,因此可以在任何地方和所有 UIFont 实例中使用;
  • 我在这里使用 Zapfino 只是为了使更改更加明显;
  • 欢迎您对此代码进行任何改进。


This solution uses two different methods to achieve the final result. The first is override the UIFont class methods + systemFontWithSize:and similar with ones that use my alternatives (here I use "Zapfino" to leave no doubts that the replacement was successful).

该解决方案使用两种不同的方法来实现最终结果。第一个是覆盖 UIFont 类方法,+ systemFontWithSize:并与使用我的替代方法的方法类似(这里我使用“Zapfino”来确保替换成功)。

The other method is to override - initWithCoder:method on UIFont to replace any occurrence of CTFontRegularUsageand similar by my alternatives. This last method was necessary because I've found that UILabelobjects encoded in NIB files don't check the + systemFontWithSize:methods to get their system font and instead encode them as UICTFontDescriptorobjects. I've tried to override - awakeAfterUsingCoder:but somehow it was getting called for every encoded object in my storyboard and causing crashes. Overriding - awakeFromNibwouldn't allow me to read the NSCoderobject.

另一种方法是覆盖- initWithCoder:UIFont 上的方法,CTFontRegularUsage用我的替代方法替换任何出现的和类似的。最后一种方法是必要的,因为我发现UILabel在 NIB 文件中编码的对象不会检查+ systemFontWithSize:获取系统字体的方法,而是将它们编码为UICTFontDescriptor对象。我试图覆盖- awakeAfterUsingCoder:但不知何故它被我的故事板中的每个编码对象调用并导致崩溃。覆盖- awakeFromNib不允许我读取NSCoder对象。

#import <objc/runtime.h>

NSString *const FORegularFontName = @"Zapfino";
NSString *const FOBoldFontName = @"Zapfino";
NSString *const FOItalicFontName = @"Zapfino";

#pragma mark - UIFont category
@implementation UIFont (CustomFonts)

#pragma clang diagnostic push
#pragma clang diagnostic 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

回答by Damien Debin

To complete Sandy Chapman's answer, here is a solution in Objective-C (put this categoryanywhere you want to change UILabelAppearance):

要完成Sandy Chapman 的回答,这里是 Objective-C 中的一个解决方案(将此类别放在您想要更改的任何位置UILabelAppearance):

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

The interface file, should have this method declared publicly to be used later from places like your app delegate:

接口文件应该公开声明此方法,以便稍后从您的应用程序委托等地方使用:

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

Then, you can change the Appearancewith:

然后,您可以更改为Appearance

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

回答by ucotta

COMMENT FOR SWIFT 3.0 AND SWIFT WARNING

对 Swift 3.0 和 Swift 警告的评论

You can remove the warning message in line:

您可以在行中删除警告消息:

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

By replacing it with:

通过将其替换为:

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

回答by Amrit Tiwari

For Swift 5

对于 Swift 5

All the above answers are correct but i have done in little different way that is according to device size. Here, in ATFontManager class, i have made default font size which is define at the top of the class as defaultFontSize, this is the font size of iphone plusand you can changed according to your requirement.

以上所有答案都是正确的,但我根据设备大小以略有不同的方式完成了。在这里,在 ATFontManager 类中,我设置了默认字体大小,在类的顶部定义为defaultFontSize,这是iphone plus的字体大小, 您可以根据自己的要求进行更改。

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

I have added certain font name, for more you can add the font name and type here.

我已经添加了某些字体名称,更多你可以添加字体名称并在此处键入。

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

This class refers to device detector in order to provide appropriate font size according to device.

此类指的是设备检测器,以便根据设备提供适当的字体大小。

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

How to use.Hope it will help.

如何使用。希望它会有所帮助。

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

回答by Gingi

None of these solutions works universally throughout the app. One thing I found to help manage the fonts in Xcode is opening the Storyboard as Source code (Control-click storyboard in Files navigator > "Open as" > "Source"), and then doing a find-and-replace.

这些解决方案都没有在整个应用程序中通用。我发现有助于在 Xcode 中管理字体的一件事是将故事板作为源代码打开(在文件导航器中按住 Control 单击故事板>“打开为”>“源”),然后进行查找和替换。

回答by Javier Amor Penas

I created my own conversion of typography for Swift 4after reviewing a few posts, it covers most of the cases, such as:

在查看了一些帖子后,我为Swift 4创建了自己的排版转换,它涵盖了大多数情况,例如:

1st Add fonts to project estructure and to .plist file (with the same name):

1st 将字体添加到项目结构和 .plist 文件(同名):

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

Then

然后

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

Finally call to created method at Appdelegatelike next:

最后调用 created 方法Appdelegate如下:

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

        UIFont.overrideDefaultTypography()
        return true
    }
}