Styling on iOS

March 2019 · 5 minute read

Every application that you know contains different UI elements (UIView, UILabel, …) organized in order to shape a specific screen. Those elements can be personalized using different attributes like:

Obviously, in order to have a decent UI, we don’t want our app to have every text in the same font and size, in order to differentiate important information from less important one for example. The same goes for colors, we are all used to a green colored button for success and a red colored one for failure. However, I believe that the amount of different visual attributes must be as small as possible. From my view as a developer, the fewer attributes there are, the easier it will be to implement the design and maintain it.

It is not always an easy task, as designers are willing to make the most beautiful product, and the developer the most simple one to implement and maintain.

Despite 2 different goals, both parts have great reasons to defend their positions and sometimes, designers and developers are not aware of each other’s limitations/priorities. Indeed, something might seem easy to do in design software but quite difficult in code and vice versa.

As a developer, I always want to implement the styling of my app in an easy and reusable way as much as possible.

I have been looking for a nice way to accomplish this since I started working with iOS and have gathered the following approach from different resources and open source projects that I have been looking at, meaning that this approach might be familiar for some.

First of all, we want to place all the styling in a Styles.swift file in order to organize all the attributes in one place.

We can now create an enum for each attribute like so:

enum Colors { } 
enum Fonts { }
enum Sizes { }

We can then populate those enum with the values we want:

enum Colors { 
    static let background = "FFFFFF"
    static let main =  "333333"
    static let title = "000000"
}

enum Fonts {
    // Custom font names imported into the project
    static let LatoRegular = "Lato-Regular"
    static let LatoBold = "Lato-Bold"

    static let title = UIFont(name: Fonts.LatoBold, size: 22)
    static let body = UIFont(name: Fonts.LatoRegular, size: 14)
    static let button = UIFont(name: Fonts.LatoBold, size: 16)
}

enum Sizes {
    static let buttonHeight: CGFloat = 42
    static let margin: CGFloat = 18
}

For the colors, I like using the hexadecimal values since it’s easy to import from design software.

We can also wrap those enums to take advantage of the auto-completion like so:

enum Styles {

    enum Colors { 
        static let background = "FFFFFF" 
        static let main = "333333" 
        static let title = "000000"
    }

    enum Fonts { 
            // Custom font names imported into the project
            static let LatoRegular = "Lato-Regular"
            static let LatoBold = "Lato-Bold"

            static let title = UIFont(name: Fonts.LatoBold, size: 22)
            static let body = UIFont(name: Fonts.LatoRegular, size: 14)
            static let button = UIFont(name: Fonts.LatoBold, size: 16)
    }

    enum Sizes { 
        static let buttonHeight: CGFloat = 42 
        static let margin: CGFloat = 18
    }

}

It is now easy to use those attributes in our code:

let customView = UIView()
customView.backgroundColor = UIColor.fromHex(Styles.Colors.background)

let titleLabel = UILabel()
titleLabel.textColor = UIColor.fromHex(Styles.Colors.title)
titleLabel.font = Styles.Fonts.title

You can’t initialize a UIColor by its hexadecimal value by default in iOS/Swift, but this can be achieved by using this extension that I first encountered on the GitHawkApp open source project.

import UIKit

extension UIColor {

    public static func fromHex(_ hex: String) -> UIColor {
        var cString:String = hex.trimmingCharacters(in: .whitespacesAndNewlines).uppercased()

        if (cString.hasPrefix("#")) {
            cString.remove(at: cString.startIndex)
        }

        if ((cString.count) != 6) {
            return UIColor.gray
        }

        var rgbValue:UInt32 = 0
        Scanner(string: cString).scanHexInt32(&rgbValue)

        return UIColor(
            red: CGFloat((rgbValue & 0xFF0000) >> 16) / 255.0,
            green: CGFloat((rgbValue & 0x00FF00) >> 8) / 255.0,
            blue: CGFloat(rgbValue & 0x0000FF) / 255.0,
            alpha: CGFloat(1.0)
        )
    }

}

There are numerous advantages to use this approach for your styling. The obvious one in that you can use those attributes easily in your UI elements as we saw previously.

Another one is if the value of an attribute must be changed, let’s say you have to replace "FFFFFF" by "333333" for Styles.Colors.background, you only have to manage the change once in the Styles.swift and all your UI elements using this styling attributes will be updated. This is way better than changing the attribute for each UI element in your code base.

This approach is also pushing the developer and the designer to collaborate. Using it enables great reusability of the different UI attributes, but can turn to be really messy if the design contains many different attributes.

As you might expect though, it is also better to start this approach at the beginning of a project and with Design Guidelines given by the designer. By Design Guidelines I mean a document referencing all different attributes used in the project. Here is an example of such document from Greg Dlubacz (Source: dribble.com).

You can see how easy to create the Styles.swift file once you have such specifications.

Moreover, this approach is also flexible. The example I gave is relatively simple, but if you need to have more attributes, it is possible to add more granularity in order to keep the overall structured, we can think of something like:

enum Styles {

    enum Colors { 

                enum Shared {
                    static let title = "000000"
                }

                enum ThatScreenOrFeature {
                    static let background = "FFFFFF"
                }

                enum ThatOtherScreenOrFeature {
                    static let background = "999999"
                }

    }

}

How about you? How do you manage the styling of your app? Do you use this approach, a similar or a totally different one?

I really hope you like this article. Do not hesitate to give your feedback about it.