使用Swift 4根据当前字体重量更改应用程序中的所有UILabel字体

时间:2017-09-25 11:50:35

标签: ios swift fonts uilabel swift4

在Swift 3中,我使用以下内容替换AppDelegate中BOLD到MEDIUM中的所有字体:

UILabel.appearance().substituteFontNameBold = "HelveticaNeue-Medium"

将此扩展名添加到UILabel:

extension UILabel {
    var substituteFontNameBold : String {
        get { return self.font.fontName }
        set {
            if self.font.fontName.contains("Bold") {
                self.font = UIFont(name: newValue, size: self.font.pointSize)
            }
        }
    }
}

升级到Swift 4后,我收到了“ 致命错误:在展开可选值 时意外发现nil

if self.font.fontName.contains("Bold") {

如何使用Swift 4继续将BOLD中的所有字体替换为标签?

3 个答案:

答案 0 :(得分:4)

Swift 4.0

这将帮助您为所有UILabel,UIButton等设置自定义字体。只需创建一个扩展名并替换为此。

var appFontName       = "Gudea" //Please put your REGULAR font name
var appFontBoldName   = "Gudea" //Please put your BOLD font name
var appFontItalicName = "Gudea" //Please put your ITALIC font name

extension UIFont {

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

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

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

@objc convenience init(myCoder aDecoder: NSCoder) {
    if let fontDescriptor = aDecoder.decodeObject(forKey: "UIFontDescriptor") as? UIFontDescriptor {
        if let fontAttribute = fontDescriptor.fontAttributes[UIFontDescriptor.AttributeName(rawValue: "NSCTFontUIUsageAttribute")] as? String {
            var fontName = ""
            switch fontAttribute {
            case "CTFontRegularUsage":
                fontName = appFontName
            case "CTFontEmphasizedUsage", "CTFontBoldUsage":
                fontName = appFontBoldName
            case "CTFontObliqueUsage":
                fontName = appFontItalicName
            default:
                fontName = appFontName
            }
            self.init(name: fontName, size: fontDescriptor.pointSize)!
        }
        else {
            self.init(myCoder: aDecoder)
        }
    }
    else {
        self.init(myCoder: aDecoder)
    }
}

class func overrideInitialize() {
    if self == UIFont.self {
        let systemFontMethod = class_getClassMethod(self, #selector(systemFont(ofSize:)))
        let mySystemFontMethod = class_getClassMethod(self, #selector(mySystemFont(ofSize:)))
        method_exchangeImplementations(systemFontMethod!, mySystemFontMethod!)

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

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

        let initCoderMethod = class_getInstanceMethod(self, #selector(UIFontDescriptor.init(coder:))) // Trick to get over the lack of UIFont.init(coder:))
        let myInitCoderMethod = class_getInstanceMethod(self, #selector(UIFont.init(myCoder:)))
        method_exchangeImplementations(initCoderMethod!, myInitCoderMethod!)
    }
}
}

更新:Swift3.2

替换此行:

if let fontAttribute = fontDescriptor.fontAttributes[UIFontDescriptor.AttributeName(rawValue: "NSCTFontUIUsageAttribute")] as? String {

使用:

if let fontAttribute = fontDescriptor.fontAttributes["NSCTFontUIUsageAttribute"] as? String {

答案 1 :(得分:3)

我找到了解决这个问题的方法,你基本上必须添加@objc才能使其正常工作,添加后不再有nil值

@objc public var substituteFontName : String

答案 2 :(得分:1)

这可以通过覆盖系统字体来完成,如下所示:

import UIKit

struct AppFontName {
    static let regular = "DINNextLTArabic-Regular"
}

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

extension UIFont {

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

    @objc convenience init(myCoder aDecoder: NSCoder) {
        if let fontDescriptor = aDecoder.decodeObject(forKey: "UIFontDescriptor") as? UIFontDescriptor {
                let fontName = AppFontName.regular
                self.init(name: fontName, size: fontDescriptor.pointSize)!

        } else {
            self.init(myCoder: aDecoder)
        }
    }

    class func overrideInitialize() {
        if self == UIFont.self {
            let systemFontMethod = class_getClassMethod(self, #selector(systemFont(ofSize:)))
            let mySystemFontMethod = class_getClassMethod(self, #selector(mySystemFont(ofSize:)))
            method_exchangeImplementations(systemFontMethod!, mySystemFontMethod!)


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

和appDelegate

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

    UIFont.overrideInitialize()

    return true
}