UIAppearance
is an underappreciated gem in UIKit’s toolbox. It provides an elegant way to style UI elements globally across your app, thereby keeping your codebase DRY (Don’t Repeat Yourself) and maintainable. In this post, we’ll dive into UIAppearance
and learn how to harness its power to style our iOS apps effectively.
What is UIAppearance?
UIAppearance
is a protocol in UIKit that allows you to customize the appearance of all instances of a class. You can set global styles for user interface elements, which will be applied to all instances of that class.
To use UIAppearance
, you call appearance()
on a class that conforms to the protocol. This will return an instance of the class that’s configured to customize the appearance for all of its instances. Here’s a simple example:
UIButton.appearance().tintColor = .blue
In this example, we’re setting the tintColor of all UIButton instances in the app to blue. Now, every button will be blue, unless we override this setting for a specific button.
A Deeper Look at the UIAppearance Protocol
UIAppearance
is quite flexible. It allows you to customize various attributes of a UI element, such as colors, fonts, and images. However, it’s important to note that not all properties of a class are stylable using UIAppearance. Only properties marked with UI_APPEARANCE_SELECTOR
can be customized.
To see which properties of a class are stylable using UIAppearance, you can refer to the class’s documentation.
UIAppearance Inheritance and Specificity
UIAppearance
respects the inheritance hierarchy of classes. If you set an appearance property on a superclass, it will apply to all of its subclasses, unless you override it for a specific subclass.
For instance, if you set the tintColor for UIView
, it will apply to all subclasses of UIView
(including UIButton
, UILabel
, etc.), since they inherit from UIView
:
UIView.appearance().tintColor = .blue
However, if you want buttons to have a different tintColor, you can override it for UIButton
:
UIButton.appearance().tintColor = .green
Now, all UIButton
s will be green, but other UIView
a will still be blue.
UIAppearance also allows you to set appearance properties for instances of a class when contained in an instance of a container class. This is done using the appearance(whenContainedInInstancesOf:)
method:
UIButton.appearance(whenContainedInInstancesOf: [UINavigationBar.self]).tintColor = .red
In this example, all buttons within a UINavigationBar
will be red.
Real World Examples
Let’s look at a more complex example. Suppose we want to style all navigation bars in our app to have a certain look. We can do this using UIAppearance
:
UINavigationBar.appearance().barTintColor = UIColor.systemBlue
UINavigationBar.appearance().tintColor = UIColor.white
UINavigationBar.appearance().titleTextAttributes = [.foregroundColor: UIColor.white]
Now, all navigation bars in our app will have a blue background color, white text, and white buttons.
For a more fine-grained control, we can even target a subclass of a navigation controller. Let’s say we have a subclass called SecondaryNavigationController
, and we want its navigation bar to have a different appearance:
UINavigationBar.appearance
(whenContainedInInstancesOf: [SecondaryNavigationController.self]).barTintColor = UIColor.systemPurple
UINavigationBar.appearance(whenContainedInInstancesOf: [SecondaryNavigationController.self]).tintColor = UIColor.black
UINavigationBar.appearance(whenContainedInInstancesOf: [SecondaryNavigationController.self]).titleTextAttributes = [.foregroundColor: UIColor.black]
UIAppearance’s Limitations
Despite its power, UIAppearance
is not without limitations. It can only style properties marked with UI_APPEARANCE_SELECTOR
, and the changes it makes are global and can only be overridden on a class-by-class basis. Also, its effects are not immediate – they only apply to UI elements that are created after the appearance changes are made.
Additionally, UIAppearance
does not work with Swift’s UI framework, SwiftUI. SwiftUI uses a completely different system for styling, which we won’t delve into in this post.
Conclusion
UIAppearance
is a powerful tool for styling UI elements globally across your app. Despite its limitations, it’s an excellent way to maintain a consistent look and feel, reduce code duplication, and increase maintainability.