Conditional compilation with precompiler directives in Xcode (an example using Pinch Analytics)

Xcode makes it easy to conditionally compile code based on custom precompiler flags that you can define yourself. Combined with the Prefix.pch file and macros, this makes it easy for you to selectively enable parts of your application without needlessly uglifying your code.

I just recently made use of these features to create macros for Pinch Analytics so that I can easily turn it on or off for my builds. I previously voiced concerns on Twitter about the spyware-like ways that Pinch Analytics can be used and Keith blogged about his thoughts at the time (the mainstream tech press picked up on this a little while later; see my links from yesterday for other commentary on the issue, including Pinch Media's response by adding easy-to-implement opt-out).

Having read the various opinions as well as Pinch Analytic's list of features, I can say that (as a developer), I see how invaluable it can be in gathering anonymous usage data that can then be used to improve the user experience. This must, however, be balanced with privacy concerns. The issue comes down to whether or not users are informed that usage data is being collected and whether they can easily opt out of it.

Currently, I'm only considering using Pinch Analytics during pre-release testing. However, I'm undecided as to whether to include it in the final build. If I do include it, it will be with notice and an opt-out option. Since I haven't decided, I need a way to turn off all instances of it easily if I need to later. This is where precompiler directives, the Prefix.pch file, and conditional compilation come into play to make life much easier.

A quick how-to

In MyApp_Prefix.pch, start by declaring a few macros for the most commonly-used Pinch Analytics methods (so you don't have to litter your code with #ifdef/#endif blocks). The Prefix.pch file is global in scope so any functions you define there will be available in all of your classes (this is very useful!).

#  define StartPinchAnalyticsSubBeacon(n, b) [[Beacon shared] startSubBeaconWithName:(n) timeSession:(b)];
#  define EndPinchAnalyticsSubBeacon(n) [[Beacon shared] endSubBeaconWithName:(n)];
#  define StartPinchAnalyticsSubBeacon(...)
#  define EndPinchAnalyticsSubBeacon(...)

Add Pinch Analytics to your App Delegate, surrounded by an #ifdef:

- (void)applicationDidFinishLaunching:(UIApplication *)application {

    NSLog(@"Pinch Analytics is on.")
  NSString *applicationCode = @"NotMyRealApplicationCode";
    [Beacon initAndStartBeaconWithApplicationCode:applicationCode
                  useCoreLocation:NO useOnlyWiFi:NO];


- (void)applicationWillTerminate:(UIApplication *)application {
  [[Beacon shared] endBeacon];

From there on, whenever you need to add a sub-beacon, simply use the macros you created previously. e.g.,

StartPinchAnalyticsSubBeacon(kContantNameOfSomeSubBeacon, NO);

Finally, define the conditional flag:

  1. Select Project → Edit Project Settings → Build and the Configuration(s) you want to apply the flag to.
  2. Under GCC 4.2 – Preprocessing, add your flag to the Preprocessor Macros section (PINCH_ANALYTICS_ON=YES)

And you're set. If you want to turn Pinch Analytics off (e.g., when you're ready to do your final release build), simply remove the flag from your project preferences.