One important trap I tapped into today is the following:
In many projects I saw a single app target and with different bundle identifiers set for each configuration of that target. Here things get messy. What the developers intended was to create a debug app for the debug config and a production app for the release target.
If you do so both apps will share the same NSUserDefaults when they are set up like so
var userDefaults = NSUserDefaults(suiteName: "group.com.company.myApp")
userDefaults!.setObject("user12345", forKey: "userId")
userDefaults!.synchronize()
This causes problems in many places:
- Imagine you set YES for a key when a special app-intro-screen has been shown to the user. The other app will now also read YES and don't show the intro.
- Yes some apps also store oAuth tokens in their user defaults. Anyways... Depending on the implementation, the app will recognize that there's a token and start retrieving data using the wrong token. The chance is high that this will fail with strange errors.
The solution to this problem in general is to prefix the defaults keys with the current configuration built. You can detect the configuration easily at runtime by setting different bundle identifiers for your configurations. Then just read the bundle identifier from NSBundle.mainBundle()
. If you have the same bundle identifiers you need to set different preprocessor macros like
#ifdef DEBUG
NSString* configuration = @"debug";
#elif RELEASE
NSString* configuration = @"release";
#endif
In Swift it will look almost the same:
#if DEBUG
let configuration = "debug"
#elseif RELEASE
let configuration = "release"
#endif