Auto convert systemFont to AppFont in Swift - TiepNC/Note GitHub Wiki
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
AppFont.config()
...
}
File AppFont.swift
import UIKit
final class AppFont {
static func config() {
UIFont.overrideInitialize()
}
}
private enum AppFontName: String {
case regular = "Roboto-Regular"
case medium = "Roboto-Medium"
case bold = "Roboto-Bold"
case italic = "Roboto-Italic"
}
private extension UIFontDescriptor.AttributeName {
static let nsctFontUIUsage = UIFontDescriptor.AttributeName(rawValue: "NSCTFontUIUsageAttribute")
}
private extension UIFont {
@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
}
let appFontName: AppFontName
switch fontAttribute {
case "CTFontRegularUsage":
appFontName = AppFontName.regular
case "CTFontMediumUsage":
appFontName = AppFontName.medium
case "CTFontBoldUsage":
appFontName = AppFontName.bold
case "CTFontObliqueUsage":
appFontName = AppFontName.italic
default:
appFontName = AppFontName.regular
}
self.init(name: appFontName.rawValue, size: fontDescriptor.pointSize)!
}
class func overrideInitialize() {
guard self == UIFont.self else { return }
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 systemFontMethod = class_getClassMethod(self, #selector(systemFont(ofSize:weight:))),
let mySystemFontMethod = class_getClassMethod(self, #selector(mySystemFont(ofSize:weight:))) {
method_exchangeImplementations(systemFontMethod, mySystemFontMethod)
}
// Trick to get over the lack of UIFont.init(coder:))
if let initCoderMethod = class_getInstanceMethod(self, #selector(UIFontDescriptor.init(coder:))),
let myInitCoderMethod = class_getInstanceMethod(self, #selector(UIFont.init(myCoder:))) {
method_exchangeImplementations(initCoderMethod, myInitCoderMethod)
}
}
@objc
class func mySystemFont(ofSize size: CGFloat) -> UIFont {
return UIFont(name: AppFontName.regular.rawValue, size: size)!
}
@objc
class func mySystemFont(ofSize size: CGFloat, weight: UIFont.Weight) -> UIFont {
let appFontName: AppFontName
switch weight {
case .regular:
appFontName = AppFontName.regular
case .medium:
appFontName = AppFontName.medium
case .bold:
appFontName = AppFontName.bold
default:
appFontName = AppFontName.italic
}
return UIFont(name: appFontName.rawValue, size: size)!
}
@objc
class func myBoldSystemFont(ofSize size: CGFloat) -> UIFont {
return UIFont(name: AppFontName.bold.rawValue, size: size)!
}
@objc
class func myItalicSystemFont(ofSize size: CGFloat) -> UIFont {
return UIFont(name: AppFontName.italic.rawValue, size: size)!
}
}