loading...

Custom iOS Settings per Configuration

coverback profile image Romans Karpelcevs ・2 min read

Custom iOS Settings per Configuration

Sooner or later, many companies face a need to provide extra information or customisation for an app. For me it was usually the ability to target non-production servers and choose between dev, test and prod server environments.

There are multiple ways to achieve it, and the easiest is probably providing custom Settings bundle in iOS system Settings section for your app.

Adding a Settings Bundle

Adding a settings bundle is as simple as adding a new class.

Adding a bundle to Xcode project

In the example project I’ve added two bundles, ProdSettings and DevSettings.
After you’ve added them, remove the bundles from the Copy Bundle Resources building phase, as you’ll be copying them manually in the next step.

Overriding the Bundle Based on the Configuration

In the build phases for your target, add a new build step New Run Script Phase and place it after Copy Bundle Resources one.
Adding build phase to Xcode building

The script to copy the correct bundle would look something like this:

SRC_DIR="${PROJECT_DIR}/CustomSettingsBundle"
if [ "${CONFIGURATION}" != "Release" ]; then
    cp -rf "${SRC_DIR}/DevSettings.bundle" "${BUILT_PRODUCTS_DIR}/${PRODUCT_NAME}.app/Settings.bundle"
else
    cp -rf "${SRC_DIR}/ProdSettings.bundle" "${BUILT_PRODUCTS_DIR}/${PRODUCT_NAME}.app/Settings.bundle"
fi

Usage

Just like with normal settings, accessing values happens through UserDefaults.

UserDefaults.standard.bool(forKey: "dev_preference_enabled")

Note that removing a setting from the bundle won’t clear the corresponding key in UserDefaults, and until the setting is updated at least once, it will be nil regardless of the default value in the plist of the settings bundle.

Gotchas

Settings in the end product folder have to be named Settings.bundle. Maybe you could change this requirement somewhere, but because of that example script also renames the folder itself.

iOS Settings are cached, so switching between configurations require project cleaning and may require an app reinstall to force the change of the settings contents. My suggestion would be to have beta/dev builds with separate bundle ID so you can have multiple versions of the app installed simultaneously without having to reinstall to test configurations.

Another issue is with the iOS Settings app itself. Sometimes all the apps would disappear from it, so a restart of the Settings app is often required if you switch and especially if you install an app while having Settings app open.

Alternatives?

Providing custom Settings bundle is very easy, but not very flexible. The next best thing is doing it via a special screen hidden under Debug/Beta-only button on the app’s landing screen.

The biggest gain is not having to leave the app to switch environment and not having to remember to kill the app if your settings are only read at launch-time. With a custom code you can make “Save” to perform data saving and then exit(0).

Discussion

pic
Editor guide