How to create a white label iOS app (Part 4)
Tags: ios, swift
Published: 2020-09-04 06:58:26

---
title: How to create a white label iOS app (Part 4)
published: true
date: 2020-09-04 06:56:07 UTC
tags: iOS,swift
canonical_url: https://www.rockandnull.com/how-to-create-a-white-label-ios-app-part-4/
---

On [Part3](https://dev.to/mavris/how-to-create-a-white-label-ios-app-part-3-14bm) we discussed how to use Preprocessor Flags to change the result of the `coffeeDescription` function based on which target was executing the function. As I noted, I don't like the Preprocessor Flags solution but it was good example to understand how they work.

You can download the project [here](https://github.com/Rock-and-Null/iOS---WhiteLabel/releases/tag/Part4) as we left it on [Part3](https://dev.to/mavris/how-to-create-a-white-label-ios-app-part-3-14bm).

A much better alternative is to use a `.plist` file (Properties List) for each target. We are going to create a `.plist` file for each target and we are going to load these properties in the app.

We will create 2 `.plist` files for our targets, and the name of each file it will be the Bundle ID. The **`rockandnull.com.TestCoffee.plist`** will be visible only to `TestCoffee` target and the **`rockandnull.com.RealCoffee.plist`** will be visible only to `RealCoffee` target (using target memberships).

![How to create a white label iOS app (Part 4)](https://www.rockandnull.com/content/images/2020/09/Screenshot-2020-09-04-at-12.57.12-AM.png)

The objective is to load the properties in the target using a singleton class called **`PropertiesController`.**

```
import Foundation

class PropertiesController {
    
    static let sharedInstance = PropertiesController()
    var description : String!

    func loadProperties() {
        let bundleID = Bundle.main.bundleIdentifier
        if let path = Bundle.main.path(forResource: bundleID, ofType: "plist") {
        	//CAUTION: We are not using best practices for simplicity. Using plain string as a key and force unwrapping is prone to errors.
            if let nsDictionary = NSDictionary(contentsOfFile: path) {
                self.description = nsDictionary["description"] as? String ?? ""
            }
        }
    }
}

```

The **`loadProperties`**  function is responsible to load the specific `.plist` file using the Bundle ID (that's why we named our .plist files after the Bundle ID). Then it converts the `.plist` file to an `NSDictionary` and then assigns the value of each key to the specific properties.

<iframe width="100%" height="386" scrolling="no" border="no" allowtransparency="true" frameborder="0" style="border:none!important;width:100%!important;height:386px;position:relative;" src="https://upscri.be/ltv52r?as_embed=true"></iframe>

We need to load the properties first thing, so we are going to add this code in **`AppDelegate`**

```
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
        // Override point for customization after application launch.
        PropertiesController.sharedInstance.loadProperties()
        return true
}
```

Then we will modify our `coffeeDescription` function in **`Coffee`** class

```
 static func coffeeDescription() -> String {
      return PropertiesController.sharedInstance.description
 }
```

The last thing (I promise) to complete this approach is to add a property (String) in **`rockandnull.com.TestCoffee.plist`** with the key `description` and value `TestCoffee`. Repeat the procedure for `RealCoffee` and set the value as `RealCoffee`.

Now we will run the app and we will notice that we have accomplished the same result with the Preprocessor Flags solution.

So, why the fuss? It's a much cleaner solution. In [Part3](https://dev.to/mavris/how-to-create-a-white-label-ios-app-part-3-14bm) we had only 2 targets and we used 7 lines of code. Imagine how much boilerplate code we would end up having in a project with 30 targets. With the `.plist` solution, our function's size will remain the same no matter how many targets we have added.

Also, you can add other types of data in the `.plist`, like a number, a boolean, a date, etc. I use the `.plist` approach to store the API endpoint, a copy that is different for each brand and specific color as HEX. This approach will work nicely if you discuss it with your designer and ask him/her to group the project colors in let's say, 6 groups. Then you will create 6 properties and you will assign the HEX code for each color and load them in `PropertiesController` as we did with description. Now, for each view that you want to set a color you will use the `PropertiesController.sharedInstance.Colour1`. That's it you can now change the colors of the whole app from the `.plist` file.

**Use with caution!** Don't use the `.plist` approach to store sensitive data. A `.plist` file is unencrypted and can easily be fetched from a device. I can't stress this enough!

Happy coding!

[Say hello](mailto:hello@rockandnull.com) or [tweet us](https://twitter.com/rockandnull)!

[How to create a white label iOS app (Part 1)](https://www.rockandnull.com/how-to-create-a-white-label-ios-app/)
[How to create a white label iOS app (Part 2)](https://www.rockandnull.com/how-to-create-a-white-label-ios-app-part-2/)
[How to create a white label iOS app (Part 3)](https://www.rockandnull.com/how-to-create-a-white-label-ios-app-part-3/)
[How to create a white label iOS app (Part 4)](https://www.rockandnull.com/how-to-create-a-white-label-ios-app-part-4/)
[How to create a white label iOS app (Part 5)](https://www.rockandnull.com/how-to-create-a-white-label-ios-app-part-5/)