Redirecting NSLog Output to a File on Demand for iPhone Debugging

NSLog can be a great tool for debugging when developing iPhone applications. It outputs a formatted message to StdErr, which is the console view in Xcode by default. However, that doesn’t help much when you want to collect information in a file on a real device over several hours of real world usage. Sure, you can write separate routines to log information to a file yourself, but why muddy your code with all that extra code, when, instead, you can simply redirect existing NSLog output to a file?

Whenever you want to redirect NSLog output to a file, you can do so by using a simple freopen statement to redirect StdErr to a file, like this:

NSString *cachesDirectory = [NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES) objectAtIndex:0];
NSString *logPath = [cachesDirectory stringByAppendingPathComponent:@"application.log"];
freopen([logPath cStringUsingEncoding:NSASCIIStringEncoding], "a+", stderr);

The above statements will cause all output for StdErr, including all NSLog output, to be redirected to a file called “application.log”. The file will be created if it doesn’t already exist, and the output will be appended to the file contents, if one already exists. If you use “w+” as the second parameter to the freopen call, the file will be truncated, its contents erased, each time this statement is called. Notice also that the file is created in <Application_Home>/Library/Caches folder, rather than the <Application_Home>/Documents folder. Caches folder is not backed up by iTunes in the later versions of iOS, and I think is more suitable for log files.

Please note that redirecting StdErr to a file will slow down your application, depending on how much and how often you output logging information. If you want to be able to redirect StdErr back to the console, you can do so by first saving the original StdErr like this:

savedStdErr = dup(STDERR_FILENO);

And then, later when you want to revert output, you can do so like this:

fflush(stderr);
dup2(savedStdErr, STDERR_FILENO);
close(savedStdErr)

You can download a sample project implementing the above ideas here.

You can retrieve the saved file easily when you connect the device to your Mac via USB. Open Xcode, click on menu item Window -> Organizer, and click on the name of your device when the Organizer window opens. You will see a list of all applications on the device on the lower right side, titled ‘Applications’. Click on the disclosure triangle to the left of your application’s name, and you should see a row titled ‘Application Data’ and if you click on the arrow to the right, you can download all of the application data on your Mac.

get_file_from_device.png

About these ads
This entry was posted in Software and tagged . Bookmark the permalink.

8 Responses to Redirecting NSLog Output to a File on Demand for iPhone Debugging

  1. mklement says:

    Very helpful – thanks!

  2. Swetha says:

    How do i show output to console window as well as in a file simultaneously?

    • azizuysal says:

      @Swetha: You need to write your own logger class that outputs logging messages to a text file. It can simultaneously use NSLog to output to console as well.

    • stavash says:

      You can use if (!isatty(STDERR_FILENO)) {…} and conditionally defer stderr output to file only when device is not connected to the debugger.

  3. Apophenia Overload says:

    Any suggestions as to how to remotely send the log file to a server as a bug report or user feedback?

  4. Apophenia Overload says:

    And a followup question: Is it true that doing this causes considerable slowdown, because writing to the file system is slow?

  5. David Gagnon says:

    Thanks a lot, it is very useful! And, assert is logged to the file also!

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s