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.
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
UILabel, etc.), since they inherit from
UIView.appearance().tintColor = .blue
However, if you want buttons to have a different tintColor, you can override it for
UIButton.appearance().tintColor = .green
UIButtons will be green, but other
UIViewa 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
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
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:
(whenContainedInInstancesOf: [SecondaryNavigationController.self]).barTintColor = UIColor.systemPurple
UINavigationBar.appearance(whenContainedInInstancesOf: [SecondaryNavigationController.self]).tintColor = UIColor.black
UINavigationBar.appearance(whenContainedInInstancesOf: [SecondaryNavigationController.self]).titleTextAttributes = [.foregroundColor: UIColor.black]
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.
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.
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.