user11497206
user11497206

Reputation:

How to use method swizzling to change the system font used in iOS app?

I am creating an iOS app in which different fonts must be used for different languages.

I am trying to do this by using systemFont everywhere in the app and at runtime, changing what systemFont refers to depending on the language.

Following is the code used to swizzle the class methods of UIFont-

extension UIFont {
    static let setSystemFont: Void = {
        let m1 = class_getClassMethod(UIFont.self, #selector(systemFont(ofSize:)))!
        let m2 = class_getClassMethod(UIFont.self, #selector(customFont(ofSize:)))!
        method_exchangeImplementations(m1, m2)

        let m3 = class_getClassMethod(UIFont.self, #selector(preferredFont(forTextStyle:)))!
        let m4 = class_getClassMethod(UIFont.self, #selector(customFont(forTextStyle:)))!
        method_exchangeImplementations(m3, m4)

        let m5 = class_getClassMethod(UIFont.self, #selector(boldSystemFont(ofSize:)))!
        let m6 = class_getClassMethod(UIFont.self, #selector(boldCustomFont(ofSize:)))!
        method_exchangeImplementations(m5, m6)

        let m7 = class_getClassMethod(UIFont.self, #selector(italicSystemFont(ofSize:)))!
        let m8 = class_getClassMethod(UIFont.self, #selector(italicCustomFont(ofSize:)))!
        method_exchangeImplementations(m7, m8)

        let m9 = class_getClassMethod(UIFont.self, #selector(systemFont(ofSize:weight:)))!
        let m10 = class_getClassMethod(UIFont.self, #selector(customFont(ofSize:weight:)))!
        method_exchangeImplementations(m9, m10)

        let m11 = class_getClassMethod(UIFont.self, #selector(preferredFont(forTextStyle:compatibleWith:)))!
        let m12 = class_getClassMethod(UIFont.self, #selector(customFont(forTextStyle:compatibleWith:)))!
        method_exchangeImplementations(m11, m12)
    }()
}

private extension UIFont {
    @objc
    class func customFont(ofSize fontSize: CGFloat) -> UIFont {
        UIFont(name: "Chalkduster", size: fontSize)!
    }
    @objc
    class func customFont(forTextStyle style: UIFont.TextStyle) -> UIFont {
        UIFont(name: "Chalkduster", size: 15)!
    }
    @objc
    class func boldCustomFont(ofSize fontSize: CGFloat) -> UIFont {
        UIFont(name: "Chalkduster", size: fontSize)!
    }
    @objc
    class func italicCustomFont(ofSize fontSize: CGFloat) -> UIFont {
        UIFont(name: "Chalkduster", size: fontSize)!
    }
    @objc
    class func customFont(ofSize fontSize: CGFloat, weight: UIFont.Weight) -> UIFont {
        UIFont(name: "Chalkduster", size: fontSize)!
    }
    @objc
    class func customFont(forTextStyle style: UIFont.TextStyle, compatibleWith traitCollection: UITraitCollection) -> UIFont {
        UIFont(name: "Chalkduster", size: 15)!
    }
}

Note- Chalkduster is used so that font change is easily observed.

In applicationDidFinishLaunching(_:), the following code is called

UIFont.setSystemFont

When the app is run, I observe that for any programmatically created views, the systemFont is changed and the Chalkduster font is used.

However, for any views instantiated from xib files, the system font is not changed.

Can anyone point out how to change the system font used in the xib files without changing the font in the xib file?

Upvotes: 4

Views: 628

Answers (0)

Related Questions