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

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:


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 (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