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?
#ifdef MAC_OS_X
# define DATADIR ~/Documents
#else
NSLog(@"Not running in OS X");
#endif
This can also be used for debugging:
#ifdef DEBUG
NSLog(@"Data array is %@", self.dataArray);
#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:
#if MAC_OS_X_VERSION_MIN_REQUIRED < MAC_OS_X_VERSION_10_5
#define NSMaximumStringLength (INT_MAX - 1)
#endif
The example is rather self explanatory.
The operator defined (something) can also be used in #if statements:
#if defined(DEBUG)
// Is equivalent to
#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:
if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad)
//iPad code
else
//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