Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Changing all UILabel fonts in app depending on current font weight using Swift 4

In Swift 3, I used the following to replace all fonts in BOLD to MEDIUM in AppDelegate:

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

And by adding this extension to 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)
            }
        }
    }
}

With the upgrade to Swift 4, I get a "fatal error: unexpectedly found nil while unwrapping an Optional value" on

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

How can I continue to replace all fonts in BOLD to MEDIUM in labels with Swift 4?

like image 599
Charles Rostaing Avatar asked Sep 25 '17 11:09

Charles Rostaing


1 Answers

Swift 4.0

This will help you set custom font for all of your UILabel, UIButton, etc. Simply create a extension and replace with this.

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

Update: Swift3.2

replace this line:

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

with:

if let fontAttribute = fontDescriptor.fontAttributes["NSCTFontUIUsageAttribute"] as? String {
like image 75
Litle Dev Avatar answered Sep 19 '22 01:09

Litle Dev