Yet Another Debug Output (NSLog Replacement)

November 18, 2008

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.

1
2
3
4
5
6
7
8
9
10
11
12
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:

1
2
3
4
5
6
7
8
9
10
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.

9 comments

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]);

by SlaunchaMan on Mar 1, 2009. #

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.

by John on Mar 1, 2009. #

Thanks for the post.

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

by John Dell on Jan 21, 2011. #

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?

Regards,
Tim

by Tim on Jan 21, 2012. #

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

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

by Jeff on Mar 18, 2012. #

Stumbled on this one somewhere…

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

by Critter on Apr 24, 2012. #

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

by Thanh Tran on Apr 8, 2013. #

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.

by John Muchow on Apr 8, 2013. #

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

by Alok Badola on Apr 8, 2013. #