Popular Tags

Who's online

There are currently 0 users and 6 guests online.

User login

A Quieter NSLog()

For some people, NSLog() writes out entirely too much stuff, including the program name, process ID, and current time down to the subsecond level. (Typical NSLog() output looks like: 2008-07-11 15:05:07.582 MyApp[1465] output.) Note that printf() can't be used as a drop-in replacement for NSLog() because it doesn't support the %@ format specifier for NSString objects. (If you're shaky on what format specifiers are, visit this article on Apple's site, and perhaps this brief tutorial to brush up on usage.)

QuietLog() is basically an Objective-C friendly version of printf() that you can use wherever you would normally use NSLog() (but would rather not see the extra spewage it produces). It accepts and outputs an NSString with printf-style format, including a variable number of parameters. For example, QuietLog(@"I have %d dogs and %d cats", dogs, cats); would print something like I have 5 dogs and 2 cats and a newline. Below are two possible implementations — the former uses a method only available in 10.5+ but the two versions are pretty much equivalent.

For 10.5 and later

void QuietLog (NSString *format, ...) {
    if (format == nil) {
        printf("nil\n");
        return;
    }
    // Get a reference to the arguments that follow the format parameter
    va_list argList;
    va_start(argList, format);
    // Perform format string argument substitution, reinstate %% escapes, then print
    NSString *s = [[NSString alloc] initWithFormat:format arguments:argList];
    printf("%s\n", [[s stringByReplacingOccurrencesOfString:@"%%" withString:@"%%%%"] UTF8String]);
    [s release];
    va_end(argList);
}

For 10.0 and later

void QuietLog (NSString *format, ...) {
    if (format == nil) {
        printf("nil\n");
        return;
    }
    // Get a reference to the arguments that follow the format parameter
    va_list argList;
    va_start(argList, format);
    // Perform format string argument substitution, reinstate %% escapes, then print
    NSMutableString *s = [[NSMutableString alloc] initWithFormat:format arguments:argList];
    [s replaceOccurrencesOfString:@"%%"
                       withString:@"%%%%"
                          options:0
                            range:NSMakeRange(0, [s length])];
    printf("%s\n", [s UTF8String]);
    [s release];
    va_end(argList);
}

The call to -initWithFormat:arguments: constructs a formatted string using an arbitrary number of parameters. The resulting string has %% replaced with %, which must be reversed before sending it to printf(). You can also replace printf("%s\n", ...) with fprintf(stderr, "%s\n", ...) if desired.

If, like me, you prefer less information but would find it useful to also print the filename and line number where the call occurred, you could use something like this macro in concert with the above function:

#ifndef LocationLog
#define LocationLog(format,...) \
{ \
    NSString *file = [[NSString stringWithUTF8String:__FILE__] lastPathComponent]; \
    printf("%s:%d - ", [file UTF8String], __LINE__); \
    QuietLog((format),##__VA_ARGS__); \
}
#endif

For example, LocationLog(@"Hello World!"); would produce something like main.m:15 - Hello World!

In addition to  __FILE__ and  __LINE__, you can use __PRETTY_FUNCTION__ in a #define macro to get output like -[MyController awakeFromNib] when called from Objective-C methods. (From C code, it just prints the name of the calling function.)

This information was distilled from this post on Borkware.com, which could also be combined with the above approaches to customize the output exactly how you like it.

Where to Add This Code

For small programs, a handy place to put such code is in main.m, so everything in the application has access to it.

For larger compilation units, you'll want to declare the function (as shown below, using the extern keyword) in a header file that is included by any file that needs to use it (such as an Xcode pre-compiled header), then define it exactly as shown above in a .m file.

extern void QuietLog (NSString *format, ...);

Other Alternatives

The Log4Cocoa project is an Objective-C port of log4j, the popular Java based logging package.

Redirected NSLog()

Occasionally, you may want to redirect your NSLog() output to a file so that you can examine it more conveniently. NSLog() works by outputting messages to STDERR, so all you need to do is redirect the STDERR stream to a file, and you're good to go. The following code will redirect it to a file on your desktop:

int fd = creat ("/Users/dave/Desktop/my_log", S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
close (STDERR_FILENO);
dup (fd);
close (fd);
NSLog(@"this will be written to my_log");

This will only affect NSLog() calls from your application.

NSLog() and Console.app

For yet another take on logging with NSLog, and specifically how it has changed in Leopard, visit the following URL:

http://lapcatsoftware.com/blog/2008/01/06/logging-in-leopard/

#define log

You can put a custom log type in the prefix header file or any other global header.
It also allows you to disable logs completely by using #ifdefs

#define ExtendedLog( s, ... ) { \
NSLog( @"<%@:(%d)> %@ \t", [[NSString stringWithUTF8String:__FILE__] lastPathComponent], \
                             __LINE__, [NSString stringWithFormat:(s), ##__VA_ARGS__] ) \
}

Your rating: None Average: 4.3 (10 votes)

Search

UPDATES

The site has recently been updated. You may notice some of the following issues:

  • Some URLs no longer work. Please use the search box.
  • File uploads should now be working. If you experience problems, please contact us.