Online Book Reader

Home Category

iOS Recipes - Matt Drance [72]

By Root 209 0
’t it be nice if internal code could use the property to set the state over time? Class extensions allow this too. So although the public property in the header is readonly:

@property (nonatomic, assign, readonly, getter=isInStock) BOOL inStock;

our class extension enables private readwrite access. Here, now, is the full private class extension for PRPModernBook:

ClassExtension/PRPModernBook.m

@interface PRPModernBook ()

@property (nonatomic, retain) id privateContext;

@property (nonatomic, assign, readwrite, getter=isInStock) BOOL inStock;

- (void)refreshStock;

@end

We’ve done a whole lot here: made a much clearer contract with whoever reads the headers, obscured private data and API from the reader, and given private callers enhanced property access over public callers. We’ve even reduced the amount of code we have to write!

The Objective-C 2.0 modern runtime and class extensions can help you write more readable, structured, and maintainable code. You’ll see them used frequently in this book; we hide boring details and private features in class extensions (and eliminate redundant ivars altogether) so that the headers are very clear about how the class should be used. As a class gets larger over time, this technique only becomes more valuable.

Recipe 36 Produce Intelligent Debug Output

Problem

You litter your source with printf and NSLog statements during development and spend hours commenting them out when it’s time to ship. Extraneous log statements hurt performance and can reduce the life span of a device’s solid-state drive. You’re looking for a way to simplify the process of removing this log output.

Solution

A good 90 percent of log output, maybe even more, exists only to aid us during the development process. Error reporting is still necessary in production code, but most of the log statements we write will eventually need to go away. Xcode makes it easy to support conditional logging based on a project’s build configuration. With just a few lines of code and a single change to our target or scheme settings, we can have log statements that magically disappear for our Release and Distribution builds.

When it comes to basic logging, Cocoa’s NSLog function is handy, but it’s both unconditional and not very customizable. Here we’ll create a logging function that allows us to fine-tune the information logged with each call and also turn itself off when running in nondebug configurations.

We start by writing the new logging function, PRPDebug. This function takes a format string with variable arguments, just like NSLog. With every call, it additionally prints the following:

Timestamp

Process name

Originating filename and line number

DebugOutput/Classes/PRPDebug.m

void PRPDebug(const char *fileName, int lineNumber, NSString *fmt, ...) {

va_list args;

va_start(args, fmt);

static NSDateFormatter *debugFormatter = nil;

if (debugFormatter == nil) {

debugFormatter = [[NSDateFormatter alloc] init];

[debugFormatter setDateFormat:@"yyyyMMdd.HH:mm:ss"];

}

NSString *msg = [[NSString alloc] initWithFormat:fmt arguments:args];

NSString *filePath = [[NSString alloc] initWithUTF8String:fileName];

NSString *timestamp = [debugFormatter stringFromDate:[NSDate date]];

NSDictionary *info = [[NSBundle mainBundle] infoDictionary];

NSString *appName = [info objectForKey:(NSString *)kCFBundleNameKey];

fprintf(stdout, "%s %s[%s:%d] %s\n",

[timestamp UTF8String],

[appName UTF8String],

[[filePath lastPathComponent] UTF8String],

lineNumber,

[msg UTF8String]);

va_end(args);

[msg release];

[filePath release];

}

The timestamp and process name resemble information provided by NSLog, though formatted a bit differently so the two styles can be easily distinguished. The debugFormatter object is statically allocated because initializing an NSDateFormatter object is very expensive. If we created a new formatter with each call, heavy use of PRPDebug could significantly affect our application’s performance. iOS 4.0 introduces new class methods on NSDateFormatter that relieve

Return Main Page Previous Page Next Page

®Online Book Reader