Had the same problem with a theme-able app.
1. Add this extension
// UIButton+TitleLabelFont.swift
import UIKit
extension UIButton {
var titleLabelFont: UIFont! {
get { return self.titleLabel?.font }
set { self.titleLabel?.font = newValue }
}
}
2. Then setup the UIButton
appearance prototype object
class Theme {
static func apply() {
applyToUIButton()
// ...
}
// It can either theme a specific UIButton instance, or defaults to the appearance proxy (prototype object) by default
static func applyToUIButton(a: UIButton = UIButton.appearance()) {
a.titleLabelFont = UIFont(name: FONT_NAME_DEFAULT, size:20.0)
// other UIButton customizations
}
}
3. Drop the theme setup in app delegate
func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool {
Theme.apply()
// ...
return true
}
If you're preloading stuff (lazy var
VCs from storyboards) earlier, it may be better to instead of using app delegate setup the theme stuff in an override initializer like so:
private var _NSObject__Theme_apply_token: dispatch_once_t = 0
extension NSObject {
override public class func initialize() {
super.initialize()
// see also: https://mcmap.net/q/911051/-why-am-i-getting-deadlock-with-dispatch_once
var shouldRun = false
dispatch_once(&_NSObject__Theme_apply_token) {
shouldRun = true
}
if shouldRun {
Theme.apply()
}
}
}
UILabel.appearance(whenContainedInInstancesOf: [UIButton.self]).font = ...
– Ceiba