Different Settings app entries for Debug vs. Release builds

So compiler directives can only take you so far when building your Objective-C iOS apps, especially when you have testers who want to keep switching things up. Rebuilding and redeploying is not the end of the world, but it gets old quick.

Luckily I figured out how to switch up the Settings.bundle file so that I can have one version for the release app, and a different version with some extra options for the debug build. This way, they don’t have to drop by every hour when they want to change something that would previously require me to comment in/out some compiler directive and rebuild and redeploy.

The theory behind this is to create a new Settings_Debug.bundle file in the same location as the current Settings.bundle file, change up the plist for your additional settings, and then in the build process, just replace the plist file in Settings.bundle with the one from the Settings_Debug.bundle file. Sounds easy, right?

Here is basically what you need to do step by step:

  • Create a new Settings_Debug.bundle file
  • Copy the plist from Settings.bundle and make the necessary modifications in the Settings_Debug.bundle
  • Click the project in file explorer, select target, select Build Phases
  • Leave release version Settings.bundle in the Copy Bundle Resources, but remove Settings_Debug.bundle from Copy Bundle Resources
  • Click Add Build Phase > Add Run Script
  • Copy following into text view below Shell
if [ "${CONFIGURATION}" == "Debug" ]; then
cp -r "${PROJECT_DIR}/Shared/Settings_Debug.bundle/Root.plist" "${BUILT_PRODUCTS_DIR}/${PRODUCT_NAME}.app/Settings.bundle/Root.plist"
echo "Debug settings bundle copied"
else
cp -r "${PROJECT_DIR}/Shared/Settings.bundle/Root.plist" "${BUILT_PRODUCTS_DIR}/${PRODUCT_NAME}.app/Settings.bundle/Root.plist"
echo "Release settings bundle copied"
fi

Here are a few caveats to keep in mind…

  • In my example above, note that my Settings.bundle file is in a folder called Shared off the project directory
  • I am not using the Root.strings file
  • It was done this way because just copying the .bundle file threw errors trying to copy the .svn files and folders
  • For me, it seems way easier to work with Root.plist in source code mode instead of property list mode

BTW, it was pretty slim pickings (not Slim Pickens, one of the great characters of all time) on the births, deaths, and events for September 21, so let me just wish everyone a Happy International Day of Peace.

Objective-C preprocessor paranoia

I am always deathly afraid of test code working its way into a release app. Usually for me this happens when I am trying to optimize a portion of the code by modifying something that is already there and working, which usually leads to something like this in my code during development:

//#define SAFE_OPTION_1
//#define RISKY_OPTION_2
#define DANGEROUS_OPTION_3

So finally I started to set it up so that I can verify that, at least for the archival build of the app, that the wrong option is not selected by using something like this:

#ifndef DEBUG_VERSION
 #if !defined(SAFE_OPTION_1)
  #error The release build of MyApp must have the SAFE_OPTION_1 option selected.
 #endif
#endif

This code will give me a build error if I forget to set the option back to the safe option, which is good.

Also, I wanted to make sure that one of the three options was selected, as commenting out all 3 options is not good, and may not necessarily generate any build errors on their own. So I then figured out that this would do the trick for me:

#if !defined(SAFE_OPTION_1) && !defined(RISKY_OPTION_2) && !defined(DANGEROUS_OPTION_3)
 #error Please select an option.
#endif

Now I get a build error when I accidentally have all 3 options commented out.

BTW, Happy 20th Birthday to the X-Files, which first aired on this date in 1993. I think it is about time for me to go back through and binge watch all 9 seasons of the show.