Learn Objective-C: Conditional Compilation

Building off of last week’s post, there are a few more preprocessor directives that allow you to control which portions of a program are compiled.

The #ifdef#endif#else, and #ifndef Statements

Sometimes (and hopefully not often), a program relies on system- or platform-specific features that must be written differently across different platforms. For example, not all iOS devices can run iOS 4.x, so any program that uses 4.x features must check to see if the system can support that feature. Or an application for OS X can check for the architecture of the system, PowerPC or Intel, or the version of the OS.

The The #ifdef, #endif, and #else directives work just like the The #ifdef, #endif, #elseif…else construct; the #endif directive is used to end an #ifdef block, just like a curly brace ( } ) ends an if block.

Note that a definition such as

#define POWER_PC

is sufficient to pass the #ifdef test; no value actually has to be specified for the constant.

So how does it work?

  1. #ifdef MAC_OS_X
  2. #   define DATADIR ~/Documents
  3. #else
  4.     NSLog(@"Not running in OS X");
  5. #endif

This can also be used for debugging:

  1. #ifdef DEBUG
  2.     NSLog(@"Data array is %@", self.dataArray);
  3. #endif

This makes the code (your debugging intentions) clearer. When the program is working properly, you can undefine DEBUG and the NSLogs will not even be compiled in.

The #ifndef statement is the exact opposite of #ifdef—the code that follows gets executed only if the value is not defined.

The #if and #elif Directives

These directives are similar to if()… and else if()…. For example, the following appears in NSString.h:

  1. #if MAC_OS_X_VERSION_MIN_REQUIRED < MAC_OS_X_VERSION_10_5
  2. #define NSMaximumStringLength     (INT_MAX - 1)
  3. #endif

The example is rather self explanatory.

The operator defined (something) can also be used in #if statements:

  1. #if defined(DEBUG)
  2. // Is equivalent to
  3. #ifdef DEBUG

A common use of this is #if defined (DEBUG) && DEBUG, which will be true if DEBUG has been defined to a non-zero value.

The #undef Operator

The #undef operator undefines a name:

#undef DEBUG

Subsequent #ifdef DEBUG and #if defined(DEBUG) statements evaluate to false.

Determining iPads

Conditional compilation can be useful in determining if you’re running on an iPad or not. Apple provides a UIUSERINTERFACE_IDIOM() macro that can perform the check for you:

  1. if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad)
  2.     //iPad code
  3. else
  4.     //iPhone code

If you have extensive code changes or want to load a different set of resources for example, the iPad code won’t ever get compiled for the iPhone and vice versa, which could simplify the resulting binary (remember, only apps under 20MBs can be downloaded off a 3G connection. You want to make your app as small as reasonably possible).

This post is part of the Learn Objective-C in 24 Days course.

Author: Feifan Zhou