Saturday, May 2, 2009

Introducing CFLog

In Foundation, there is a very handy printf-like function for debugging, called NSLog. You can call it like this:

NSLog(@"%@'s temperature is %f K", [NSDate date], 310.f);

In CoreFoundation, however, there is just a single-argument CFShow. This forces the simple NSLog line split into 3:

CFStringRef debugString = CFStringCreateWithFormat(kCFAllocatorDefault, NULL, CFSTR("%@'s temperature is %f K"), [NSDate date], 310.f);
CFShow(debugString);
CFRelease(debugString);


This is very annoying when you have lots of code like these. Of course we can always define a macro or function to take out all the repeating parts, e.g. in MobileSubstrate's source code:

#define CFLog(args...) \
do { \
CFStringRef string(CFStringCreateWithFormat(kCFAllocatorDefault, NULL, args)); \
CFShow(string); \
CFRelease(string); \
} while(0)


But there is actually a more powerful CFLog built into CoreFoundation. It is, unsurprisingly, called CFLog:

/*
APPLE SPI: NOT TO BE USED OUTSIDE APPLE!
*/

enum { // Legal level values for CFLog()
kCFLogLevelEmergency = 0,
kCFLogLevelAlert = 1,
kCFLogLevelCritical = 2,
kCFLogLevelError = 3,
kCFLogLevelWarning = 4,
kCFLogLevelNotice = 5,
kCFLogLevelInfo = 6,
kCFLogLevelDebug = 7,
};

CF_EXPORT void CFLog(int32_t level, CFStringRef format, ...);


The header code can be found in http://www.opensource.apple.com/darwinsource/10.5.6/CF-476.17/CFLogUtilities.h (requires login). This is available on the iPhoneOS too as an undocumented function starting from 2.2. So you can now do it like this instead:

CFLog(kCFLogLevelDebug, CFSTR("%@'s temperature is %f K"), [NSDate date], 310.f);

Simple and beautiful.

No comments:

Post a Comment