A tweak to a better NSLog()

Recently I wanted to make sure my NSLog()’s were not present in my release build. And so I did the requisute google knowing I could copy and paste some snippet of #if…#endif.

There was just one such approach in the Cocoa Is My Girlfriend site of DroppingNSLog in release builds but even a bit nicer was the actual debug output produced in Karl’s article: A drop-in replacement for NSLog(). Better debug logging was one of those things which is a really low level priority so you never get around to it, but it would be nicer to have better logging.

So I went with Karl’s in the end but I’ll just note that to get it going there was a slight problem with Karl’s version, that only showed up if you have code of the form:

if (sometest)
   DebugLog(....);
else
   DebugLog(...);

To make things work one has to be careful about the terminating semi-colons, and the null case. This is a standard trick in C++ and I have seen it in many other places the do {} while(0) to put in an empty statment in a hash-define. So in the end the final version should be to replace all NSLog(…) calls with DebugLog(…) and add the following to an appropriately common header in your personal project:

#ifdef DEBUG
#  define DebugLog(args...) _DebugLog(__FILE__,__LINE__,__PRETTY_FUNCTION__,args)
#else
#  define DebugLog(x...) do {} while(0)
#endif
void _DebugLog(const char *file, int lineNumber, const char *funcName, NSString *format,...);

This together with his original code in the corresponding .m file of:

void _DebugLog(const char *file, int lineNumber, const char *funcName, NSString *format,...)
{
    va_list ap;

    va_start (ap, format);
    if (![format hasSuffix: @"\n"])
        format = [format stringByAppendingString: @"\n"];

    NSString *body =  [[NSString alloc] initWithFormat: format arguments: ap];
    va_end (ap);
    const char *threadName = [[[NSThread currentThread] name] UTF8String];
    NSString *fileName=[[NSString stringWithUTF8String:file] lastPathComponent];
    if (threadName)
        fprintf(stderr,"%s/%s (%s:%d) %s",threadName,funcName,[fileName UTF8String],lineNumber,[body UTF8String]);
    else
        fprintf(stderr,"%p/%s (%s:%d) %s",[NSThread currentThread],funcName,[fileName UTF8String],lineNumber,[body UTF8String]);
    [body release];
}

Will do the trick nicely. Don’t forget to go into the targets and define -DDEBUG on your debug target like so:

Build Settings

Leave a Comment