Online Book Reader

Home Category

iOS Recipes - Matt Drance [73]

By Root 275 0
us of this optimization burden, but since this recipe is particularly useful, we decided to keep it compatible with 3.0 and later.

The filename and line number are very valuable: they tell us exactly where in our code a particular log statement is coming from. We’ll see how that information is generated in a moment.

By setting this flag only for the Debug configuration, you automatically omit the PRPDebug output from any other configurations you create (for example, Release or App Store).

Figure 35. Conditionally enabling debug output

* * *

So, we’ve written a function called PRPDebug. You may have noticed, however, that the code in DebugOutputAppDelegate calls PRPLog. What is PRPLog? It is, in fact, a macro. This is what we use to enable conditional execution of the log statements.

DebugOutput/Classes/PRPDebug.h

#ifdef PRPDEBUG

#define PRPLog(format...) PRPDebug(__FILE__, __LINE__, format)

#else

#define PRPLog(format...)

#endif

The PRPLog macro looks for a PRPDEBUG definition: if PRPDEBUG exists, PRPLog passes its varargs, along with the aforementioned filename and line number, to PRPDebug. Since it uses the __FILE__ and __LINE__ preprocessor macros, this information is always correct, wherever we may copy and paste these statements.

If PRPDEBUG does not exist, PRPLog evaluates to a nop at build time. This is an important distinction; because we are using a macro, the debug code does not even make it into the binary when PRPDEBUG is undefined. There is therefore no performance hit when logging is disabled.

So, how and where is PRPDEBUG defined? In your Xcode project build settings. Select your project or target in the Groups & Files pane, and then click the Build tab. Find the Other C Flags setting under GCC 4.2 - Language (you can use the search field to find it), and type -DPRPDEBUG. Confirm that the flag is listed only under the Debug configuration and that your Release configuration does not include it. This flag triggers the appropriate macro definition for PRPLog and effectively enables or disables logging. The -D is important if you’re using Other C Flags; you can omit the -D if you’d rather use the Preprocessor Macros build setting. Either approach works for this exercise. When you’re done, you should see something like the screenshot in Figure 35, Conditionally enabling debug output .

Double-check your schemes in Xcode 4 to make sure the build configurations you expect are in use. The Run operation uses the Debug build configuration by default.

Figure 36. Schemes and build configurations

* * *

Build and run the DebugOutput project under both Debug and Release to see the difference in output. The “This is a PRPLog...” output should be visible in the console only when building and running the Debug configuration; Release builds should not display any PRPLog output. You can switch between build configurations in Xcode 4 either by editing your current scheme or by creating a new one and editing its Run operation. Figure 36, Schemes and build configurations shows how to change build configurations for a given scheme operation.

Note that, in the example, the current class and method name are passed to PRPLog as part of the format string:

DebugOutput/Classes/DebugOutputAppDelegate.m

PRPLog(@"This is a PRPLog sent from -[%@ %@]",

NSStringFromClass([self class]),

NSStringFromSelector(_cmd));

Note also the use of [self class] and _cmd, which, like __FILE__ and __LINE__, are also dynamic and therefore future-proof. Including hard-coded class or method names in your logging statements is usually asking for trouble down the road; the alternative demonstrated here is just too easy to ignore. You can even define macros to reduce the necessary typing:

#define CMD_STR NSStringFromSelector(_cmd)

#define CLS_STR NSStringFromClass([self class])

We can also print a full signature at once using the __PRETTY_FUNCTION__ macro, which produces a C string (represented in NSLog or PRPLog format strings by a %s). In this case, we opted to use the source line number instead of the method

Return Main Page Previous Page Next Page

®Online Book Reader