Protocol-based Themes in iOS Apps

Muhammad Nayab Butt
4 min readOct 30, 2019

--

In this brief tutorial, we’ll talk about protocol-based themes in the iOS application, using the concept of Open Closed Principle.

If you don’t know about Open Closed Principle take a look at these great guides:

Coming to this article we have to build a very simple application that has 6 colors in it. First, create an Xcode project and the minimum supported version should be iOS 11.

We will be using Color Set and store our colors in Themes.xcassets. If you are not familiar with it, no problem, the process is very simple. Just right click on the project and click on New File -> Asset Catalog and name it “Theme” or whatever you like. Then to add color click on “+” button and select “New Color Set”(3rd option).

Finally, we added 6 colors. The good thing is we can use these colors and access them via attribute inspector under “Named Colors”. Moreover, we can access these colors programmatically as well.

UIColor.init(named: “BackGround”)

We have got the basic things we need, and now we will be starting our main job. First, create a new Swift file and create a “Protocol Theme” in this file. Simply copy-paste the below code.

protocol Theme {
var backgroundColor : UIColor { get }
var secondaryBackgroundColor : UIColor {get}
var heading : UIColor {get}
var subHeading : UIColor {get}
var sepratorColor : UIColor { get }
var tintColor : UIColor { get }
}

Next, we will create 2 themes one is MainTheme and another one SecondaryTheme and both these will conform to our Theme Protocol.

Copy-paste the below code snippet, and you can create as many themes as you want.

//We are accessing colours from "Theme.xcassets"struct MainTheme : Theme {
var backgroundColor: UIColor = UIColor.init(named: “BackGround”)!
var secondaryBackgroundColor = UIColor.init(named: “SecondaryBackGround”)!
var heading: UIColor = UIColor.init(named: “Heading”)!
var subHeading: UIColor = UIColor.init(named: “SubHeading”)!
var sepratorColor: UIColor = UIColor.init(named: “SeparatorColor”)!
var tintColor: UIColor = UIColor.init(named: “Tint”)!
}
struct SecondaryTheme : Theme {
var backgroundColor = UIColor.black
var secondaryBackgroundColor = UIColor.green
var heading = UIColor.black
var subHeading = UIColor.purple
var sepratorColor: UIColor = UIColor.red
var tintColor: UIColor = UIColor.green
}

To use the themes we will create a ThemesManager. The role of the theme manager is to inject our desired theme on the app launch or whenever we want. Below you will see more explanations:

class ThemesManager {
//1 var theme : Theme?
//2 static var shared : ThemesManager = {
let themeneManager = ThemesManager()
return themeneManager
}()
//3 func setTheme(theme : Theme){
self.theme = theme
}
}
  • //1. We have declared an instance of Theme Protocol. Our application will use this property throughout the application and we will not directly access MainTheme or SecondaryTheme class.
  • //2. ThemeManager’s shared instance
  • //3. setTheme(theme: Theme) this method will be used to inject the theme which we want to use throughout the application.

Finally, move into the AppDelegate and set this line in “didFinishLaunchingWithOptions” to inject a theme at launch. We can change the theme on run-time as well by executing the below line of code and assigning a different theme.

ThemesManager.shared.setTheme(theme: MainTheme())

To access a particular color simply type the below line of code.

view.backgroundColor = ThemesManager.shared.theme?.backgroundColor

In the above line of code, we ask ThemenManager to fetch the desired color from the theme we have injected at run time. In case, in future one has to use a new color scheme then they can create a new theme class and conforms it to Theme Protocol. It will save you a lot of hassle!

In the attached project open ViewController.swift file and themes are being replaced on toggle of switch button

The full project can be accessed from:

Thanks for reading!

--

--