I setup UILabel appearance in my app delegate using:
UILabel.appearance().textColor = UIColor.white
I also have a custom UIView subclass that contains a UILabel along with some other elements (omitted here):
@IBDesignable
class CustomView: UIView {
private let descriptionLabel = HCLabel()
override init(frame: CGRect) {
super.init(frame: frame)
setup()
}
required init?(coder: NSCoder) {
super.init(coder: coder)
}
override func awakeFromNib() {
super.awakeFromNib()
self.setup()
}
private func setup() {
self.descriptionLabel.textColor = UIColor.black
// ... other things not related to descriptionLabel
}
}
If I instantiate CustomView
in a storyboard, everything works just fine. If, however, I instantiate it in code, the descriptionLabel is white (appearance color), not black (the color I set). What's going on here? The way I understood it was that if I set a custom color, the appearance color will not be used.
What you're experiencing is simply a matter of the exact timing with which the UIAppearance proxy applies its settings to a new UIView. When are we to suppose it does this? It can't possibly do it before init
, because init
is the first thing that happens in the life of the UIView. Thus, the order of events is like this:
override init(frame: CGRect) {
super.init(frame: frame)
setup() // black
}
// and some time later, UIAppearance proxy comes along and sets it to white
So your goal is to call setup
pretty early in the life of the label — and certainly before the user ever has a chance to see it — but not so early that the UIAppearance proxy acts later. Let's move the call to setup
to a bit later in the life of the label:
// some time earlier, UIAppearance proxy sets it to white
override func didMoveToSuperview() {
setup() // black
}
Now we're acting after the appearance proxy has had a chance to act, and so your settings are the last to operate, and they win the day.
We remain in ignorance of how early we could move the call to setup
and still come along after the appearance proxy setting has been obeyed. If you have time, you might like to experiment with that. For example, willMoveToSuperview
is earlier; if you call setup
there (and not in didMoveToSuperview
), does that work? Play around and find out!