Using Mirror for styles in Swift

Andrei Panov
2 min readMay 2, 2017

--

Usually we use reflection approaches for testing or for building JSON from objects to represent as a dictionary to send to the server. But what if we want to apply the same technique at the UI layer?

Let’s imagine we could automatically get all UI properties (UILabel, UITextField, etc.) and apply some styles (fonts, colours, everything that we need).
It would be awesome if we could run this function once in our parent ViewController and never care about it again. 🙌
Something like:

Looks nice, but how to achieve it?

Let’s create a restriction protocol for our controllers with the following function:

It would be convenient to run this method once in our parent UIViewController.

First of all, we should create a class with all of our style configuration.
We can apply all styles using block base syntax.
For example, we’ll create closures with styles for different UI elements.

Awesome, but we have a problem here as all blocks have different types and we can’t just create an array of our blocks and apply styles one by one. Fortunately, it’s possible to create an enum to wrap it in one array to apply later. Moreother, we need to know that the style should be applied for concrete control. The easiest solution will be to define a guide notation. It should be simple and we can name our UI elements with some key words. For example, firstHeaderLabel, secondBodyLabel — contains style name header, body.
In our example we define enum cases and applicable identifiers.

Ok, now we can build our style guide:

What do we have right now? We have a bunch of styles that should be applied on our UI elements with Styleable protocol.

Good, now let’s make some magic here!

A simple way to access our properties in an array format is by using the Mirror class. We will extend our Styleable protocol a bit under the hood for applying styles with this usage.
Since our array contains enums with the “get my identifier” option, it’s easy to apply the guide. The extension will be a generic function, like func perform<T>(with identifier: String, closure: (T) -> Void), and it will be called for all of our styles in a loop. Swift will type infer from the parameter’s closure description. While looping through all our controller’s properties, we’ll check if the identifier is contained in property name and if property type is equal to the generic parameter. 👊

Finally, we just ask StyleGuide to create styles and go through the enum to understand specific types and call our “perform” method.

After some time our style could become bigger, so we should decompose this method or use a “style-guide-per-feature” principle.
As a result our controllers become nice and clean.
You can find a complete example here.

--

--