More Preprocessor Directives

Of the many other available preprocessor directives, the one you’ll use most often is #define. It is followed by a name and a value; at preprocess time, the value is substituted for the name down through this code file. As K&R very well explain (K&R 1.4), this is a good way to prevent “magic numbers” from being hidden and hard-coded into your program in a way that makes the program difficult to understand and maintain.

For example, in an iOS app that lays out some text fields vertically, I might want them all to have the same space between them. Let’s say this space is 3.0. I shouldn’t write 3.0 repeatedly throughout my code as I calculate the layout; instead, I write:

#define MIDSPACE 3.0

Now instead of the “magic number” 3.0, my code uses a meaningful name, MIDSPACE; at preprocessor time, the text MIDSPACE is replaced with the text 3.0. So it amounts to the same thing, but if I decide to change this value and try a different one, all I have to change is the #define line, not every occurrence of the number 3.0.

A #define simply performs text substitution, so any expression can be used as the value. Sometimes you’ll want that expression to be an NSString literal. Here’s why. In Cocoa, NSString literals can be used as a key to a dictionary or the name of a notification. (Never mind for now what a dictionary or a notification is.) This situation is an invitation to error. If you have a dictionary containing a key @"mykey" and you mistype this elsewhere in your code as @"myKey" or @"mikey", the compiler won’t complain, but your program will misbehave. The solution is to define a name for this literal string:

#define MYKEY @"mykey"

Now use MYKEY throughout your code instead of @"mykey", and if you mistype it (as MYKKEY or what have you), the preprocessor won’t perform any substitution and the compiler will complain, catching the mistake for you.

The #define directive can also be used to create a macro (K&R 4.11.2), a more elaborate form of text substitution. You’ll encounter a few Cocoa macros in the course of this book, but they will appear indistinguishable from functions; their secret identity as macros won’t concern you.

The #warning directive deliberately triggers a warning in Xcode at compile time; this can be a way to remind yourself of some impending task or requirement:

#warning Don't forget to fix this bit of code

There is also a #pragma mark directive that’s useful with Xcode; I talk about it when discussing the Xcode programming environment (Chapter 9).

Get Programming iOS 6, 3rd Edition now with the O’Reilly learning platform.

O’Reilly members experience books, live events, courses curated by job role, and more from O’Reilly and nearly 200 top publishers.