Cocoa and iOS Development

Archive for the ‘preprocessor macros’ tag

Preprocessor Macros

leave a comment

It’s useful to create symbols for values that are used throughout your project instead of hard-coding the same information in multiple places. Enter preprocessor macros.

There are two types of macros: object-like and function-like. Object-like macros are typically used to give symbolic names to numeric constants. They don’t take parameters and are conventionally defined in uppercase letters. Function-like macros, as their name suggests, take parameters in parenthesis (where there is no space between the parenthesis and the identifier) and are replacedby so-called “replacement tokens”.

Let’s take a look at two rudimentary examples:

1. #define VERSION 1.0

This creates an object-like macro which defines a symbol with identifier “VERSION” and replacement token “1.0″

2. #define SUM(a, b, c) a + b + c

This is an example function-like macro with identifier “SUM”, parameters “(a, b, c)” and replacement tokens “a + b + c”. Simple enough, right?

Joe and I have found it incredibly useful to use this nifty macro when printing to the console. It provides a bit more information than your basic “NSLog”. For a great discussion about its evolution, checkout Nick Dalton’s blog post.

 #ifdef DEBUG
#define DLog(fmt, ...) NSLog((@"%s [Line %d] " fmt), __PRETTY_FUNCTION__, __LINE__, ##__VA_ARGS__)
#define DLog(...)

We place this macro directly into our .pch file so that it can be called from any class without requiring an #import. In this case, it is obviously a good decision to make this globally accessible to all classes however, not all of our macros live in the .pch file. For an interesting post on .pch files, read this Cocoa Is My Girlfriend post. Here, Marcus uses the “DLog” macro as well as an additional “ALog” macro (when debugging) for throwing assertions. Here are a couple of our favorite object-like macros:

#define kMainWindow [[[UIApplication sharedApplication] delegate] window]

#define kMacDefaultDisabledAlpha 0.439216f

kMacDefaultDisabledAlpha is great for setting any UIView object to appear disabled with exactly the same alpha that Apple uses.

It is really nice to use RGB_COLOR and RGB_ALPHA_COLOR to avoid simple division when your designer gives you RGB values for in specs. I’ve also seen this functionality achieved via UIColor extensions.

#define RGB_COLOR(r, g, b) [UIColor colorWithRed:(r / 255.0f) green:(g / 255.0f) blue:(b / 255.0f) alpha:1.0f]

#define RGB_ALPHA_COLOR(r, g, b, a) [UIColor colorWithRed:(r / 255.0f) green:(g / 255.0f) blue:(b / 255.0f) alpha:(a < 1.0 ? a : (a / 255.0f))]

If you are going to be working with the documents directory or the bundle path checkout the next three macros:

#define DOCUMENT_PATH(inPath) [[NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) objectAtIndex:0] stringByAppendingPathComponent:inPath]

#define BUNDLE_PATH(inPath) [[[NSBundle mainBundle] bundlePath] stringByAppendingPathComponent:inPath]

#define TEMPORARY_PATH(inPath) [NSTemporaryDirectory() stringByAppendingPathComponent:inPath]

IS_EMPTY_STRING can take anything as a parameter (yes, even an NSNull) and it will assert whether or not you’ve got an empty string. So, the next time you’re API unexpectedly starts returning a null instead of a string, don’t worry about this macro’s integrity.

#define IS_EMPTY_STRING(inString) (!inString || (NSNull *)inString == [NSNull null] || [[inString stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]] isEqualToString:@""] || [[inString stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]] isEqualToString:@"<null>"])

That is all for now.

Written by Sarah

February 4th, 2012 at 8:51 pm