Yet Another Debug Output (NSLog Replacement)

Although NSlog is convenient for outputting messages to the console, I tire of the date/time and object information that it prints.

As an alternative, one can craft a macro that uses CFShow, which outputs Core Foundation objects to stderr. CFShow uses callbacks to objects to display their descriptions, which allows one to use “%@” like you would when calling NSLog.

I often include the following debug definition as part of my projects:

#define debug(format, ...) CFShow([NSString stringWithFormat:format, ## __VA_ARGS__]);

A few short examples follow showing the difference in output between NSLog and the debug macro shown above.

struct point
  int x;
  int y;
typedef struct point POINT;

POINT topLeft;
topLeft.x = 15, topLeft.y = 20;
NSLog(@"x: %d y: %d", topLeft.x, topLeft.y);
debug(@"x: %d y: %d", topLeft.x, topLeft.y);

The output will now look as follows:

Here’s another example, this time passing in an object:

NSDate *today = [NSDate date];
NSDateFormatter *dateFormat = [[NSDateFormatter alloc] init];
[dateFormat setDateFormat:@"EEEE MMMM d, YYYY"];
NSString *dateString = [dateFormat stringFromDate:today];
[dateFormat release];


NSLog(@"Date: %@", dateString);
debug(@"Date: %@", dateString);

And the corresponding output:

Ahhh, much better.

  1. Why not just use printf? You could do the following:

    NSDate *today = [NSDate date];
    NSDateFormatter *dateFormat = [[NSDateFormatter alloc] init];
    [dateFormat setDateFormat:@”EEEE MMMM d, YYYY”];
    NSString *dateString = [dateFormat stringFromDate:today];
    [dateFormat release];

    NSLog(@”Date: %@”, dateString);
    printf(“Date: %s”, [dateString cString]);

  2. I agree, printf will work fine as you’ve shown, however, with printf you need to call the appropriate method to convert each object to its string representation or call the description method on the object. NSLog and/or CFShow will handle this process for you.

  3. Thanks for the post.

    I added #define NSLog(…) CFShow([NSString stringWithFormat:__VA_ARGS__])
    to MyApp_Prefix.pch and it works beautifully.

  4. It doesn’t work with ARC, I get the following:

    error: Automatic Reference Counting Issue: Implicit conversion of an Objective-C pointer to ‘CFTypeRef’ (aka ‘const void *’) is disallowed with ARC

    Any thoughts?


  5. @Tim: A bridge cast seems to do the trick:

    #define debug(format, …) CFShow((__bridge void *)[NSString stringWithFormat:format, ## __VA_ARGS__]);

  6. Stumbled on this one somewhere…

    #define PrintName NSLog(@”?”, __FUNCTION__);

  7. Hi, but can u please tell me what is the benefit of this way compare to NSLog ?

    • I prefer my output not to have the date/time stamp as I rarely find it helpful. My macro keeps the output to only that which I put in the debug statement.

  8. @Jeff: can u please explain what is bridge cast as i read the apple documentation but not able to get it properly

Comments are closed.