This is a gist which should provide a modular way of adding Environment settings to your iOS or Mac application like described in the excellent article from the guys at CarbonFive.
This Framework maps different Xcode configurations, Debug and Release being the default, to different sets of settings or Environments like development, staging1, staging2, production and so on.
All the different settings are stored in the Environments.plist file as dictionaries with the given environment as the key.
Check out the gist
Execute the following script to install (Please change the variables accordingly):
# Only customization
export YOUR_TARGET=ADD_NAME_HERE
# Folders
export VENDOR_FOLDER=$YOUR_TARGET/Vendor/Environment
export PERSONAL_FOLDER=$YOUR_TARGET/Environment
# Clone the file
git clone [email protected]:2782045.git $VENDOR_FOLDER
# Add the git module
echo "
[submodule \"Environment\"]
path = ${VENDOR_FOLDER}
url = git://gist.github.com/2782045.git
" >> .gitmodules
# Create the initial files
mkdir -p $PERSONAL_FOLDER
cp $VENDOR_FOLDER/Environments.template.plist $PERSONAL_FOLDER/Environments.plist
echo "" > $PERSONAL_FOLDER/Environment+$YOUR_TARGET.h
echo "" > $PERSONAL_FOLDER/Environment+$YOUR_TARGET.m
echo "Don't forget to add the files to Xcode
$PERSONAL_FOLDER
$VENDOR_FOLDER
"
-
In your project settings on the Info tab add any new categories such as
Preview -
Add the
.h,.mand.plistfile in theEnvironmentGistdirectory to Xcode -
Add a new key to your app's
-Info.plistfile:<key>Environment</key> <string>${CONFIGURATION}</string> -
Update the
Environments.plistfile with your desired environments which should be top-level dictionaries. They need to correspond with the environments, that you have configured in your project (Step 1). -
Add a category for
Environment.hwhich contains the properties that you need:#import <Foundation/Foundation.h> #import "Environment.h" @interface Environment(YourApp) ENVIRONMENT_PROPERTY(myApiURL) @endThe implementation
#import "Environment+YourApp.h" @implementation Environment(YourApp) ENVIRONMENT_GETTER(myApiURL) @end -
Update the projects
.pchfile and add the created category:#import "Environment+YourApp.h" -
Add different bundle identifiers for the different configurations:
- For your target in Build Settings add a
User Build SettingENVIRONMENT_SUFFIXand set it to${CONFIGURATION}for all but theReleaseconfiguration. - Change the
Bundle Identifierin yourInfo.plistfile to `com.domain.yourapp${ENVIRONMENT_SUFFIX}.
This will result in
com.domain.yourapp-Debugfor example. Please note that all changes require a Clean to take effect. - For your target in Build Settings add a
-
And your icon files
CFBundleIcons.<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> <plist version="1.0"> <dict> <key>CFBundlePrimaryIcon</key> <dict> <key>CFBundleIconFiles</key> <array> <string>Icon${ICON_SUFFIX}.png</string> <string>Icon${ICON_SUFFIX}-72.png</string> <string>Icon${ICON_SUFFIX}@2x.png</string> </array> <key>UIPrerenderedIcon</key> <true/> </dict> </dict> </plist> -
Optionally, also add the same kind of suffix to the
CFBundleDisplayName
When reading a value use the following syntax to return a given value from the Environments.
[Environment sharedInstance].myApiURL
Please note that all newly defined properties should be added to your category. However, values can also be accessed like so:
[[Environment sharedInstance] valueForKey:@"myKey"]
It is possible to define an Environment as a master by adding the key _isMaster = YES as a subkey in the Environments.plist file.
Example:
Assume that there are two Configurations defined: Release and Preview. The Release Environment has the _isMaster key set.
Even if the current Envrionment is set to Preview, any values that don't exist there will be looked up in the Release Environment.
-
The Environment.plist ends up in the App bundle and is not encrypted
-
Nested substitutions of values would be cool:
baseURL = http://domain.com/api contactsURL = {baseURL}/contacts