Configuration and User-Defined setting in iOS

Support different products in the same project

Posted by Ky Nguyen on April 07, 2018

I ran into a challenge: support different countries with different app’s name, icon but same code. “Green” app is the original app, there is a need to convert the original “Green” app to another app with different properties, which in the demo is known as the “Red” app.

Cloning to different projects is not my solution. Did some research and finally, I did this solution. Use different Build Settings and Schemes for markets. This is how I did

Add configurations

  • Access to Project Setting/Info. Rename configuration Debug and Release to Debug_Red and Release_Red

  • Duplicate these 2 configurations and change name to Debug_Green and Release_Green

Add Schemes

  • Select current scheme and Edit Scheme...

  • Duplicate Scheme
  • Manage Schemes...
  • Select a scheme and press Return key to rename.

  • Double click to Scheme Red and check left hand side setting
  • Make sure Debug, Test, Analyze is Debug_Red configuration and Profile, Release is Release_Red. To change configuration, select Info and change in Build Configuration.

  • Same to Scheme Green

Add User-Defined Setting

Red and Green have different name, bundle ID, version, build number. I have to add some User-Defined Setting

  • Select Project setting/Editor/Add Build Setting/Add User-Defined

  • Add some settings: app_name, bundle_id, version, build_number
  • Add value to new settings

Bind User-Defined Setting

  • In Tab Build Setting, search Product Bundle Identifier and enter value $(bundle_id)

  • Select Tab General
  • Enter $(app_name) to Display Name, $(version) to Version, $(build_number) to Build

Result

  • Add some UILabel to Storyboard Main and connect outlets
  • Add some code to show setting of the running app.

    appNameLabel.text = Bundle.main.object(forInfoDictionaryKey: "CFBundleDisplayName") as? String
    versionLabel.text = Bundle.main.infoDictionary?["CFBundleShortVersionString"] as? String
    buildLabel.text = Bundle.main.infoDictionary?["CFBundleVersion"] as? String
    bundleIdLabel.text = Bundle.main.bundleIdentifier

  • It works

Other setting

We can apply this solution to Launchscreen, App Icon by adding 2 Launchscreens, 2 App Icons with same name, just different suffix.

We can set Launchscreen same to Display Name but App Icon needs to be configured same to Product Bundle Identifier

Besides that, we need to change font family, theme color, text color depend on App. Here how to do.

Configure in code


    protocol Configuration {
        var themeColor: UIColor { get set }
        var textColor: UIColor { get set }
    }

    struct RedConfiguration: Configuration {
        var themeColor = UIColor.red
        var textColor = UIColor.white
    }

    struct GreenConfiguration: Configuration {
        var themeColor: UIColor = UIColor.green
        var textColor = UIColor.blue
    }

In my main setting class


    let config: Configuration = {
        if let app = Bundle.main.object(forInfoDictionaryKey: "CFBundleDisplayName") as? String {
            if app == "Red" {
                return RedConfiguration()
            }
            else {
                return GreenConfiguration()
            }
        }
        
        return RedConfiguration()
    }()
    

Final

My demo source is available on Github