Search code examples
iosswiftuikituilabeluiappearance

How to make UIAppearance proxies apply to programmatically created views?


I'm trying to use UIAppearance to create a theme for my app.

Say I want all my UILabel's texts to be orange. I wrote:

UILabel.appearance(whenContainedInInstancesOf: [UIView.self]).textColor = .orange

But I realized that:

  • This worked for every UILabel created via Interface Builder.
  • This does not work for any UILabel created programmatically. They are displayed in black by default

Any idea how I can force programmatically created instances to be orange as well?

PS: I've also tried: UILabel.appearance().textColor = .green which is not what I want but it doesn't work either.


Solution

  • After some searching...

    Apparently, the fact that UI elements (such as labels) created in Interface Builder are affected by .appearance() settings is not really intentional, and is probably not reliable.

    In fact, the documentation seems rather confusing and misleading.

    To support appearance customization, a class must conform to the UIAppearanceContainer protocol and relevant accessor methods must be marked with UI_APPEARANCE_SELECTOR.

    The only classes that adopt UIAppearance protocol are

    • UIBarItem
    • UIView

    and the only classes that adopt UIAppearanceContainer protocol are

    • UIPopoverController
    • UIPresentationController
    • UIView
    • UIViewController

    So... best bet is probably to sub-class your labels.