Logging to a file on the iPhone
Asked Answered
T

5

18

What would be the best way to write log statements to a file or database in an iPhone application?

Ideally, NSLog() output could be redirected to a file using freopen(), but I've seen several reports that it doesn't work. Does anyone have this going already or have any ideas how this might best be done?

Thanks!

Twocolor answered 14/10, 2008 at 18:36 Comment(0)
A
18

I've successfully used freopen(...) on the phone to re-direct output to my own file.

Anthropomorphize answered 14/10, 2008 at 18:52 Comment(5)
Do you remember which arguments you used?Twocolor
I used freopen([newFileName UTF8String], "w+", stderr), which redirected all console output to logFileName.Anthropomorphize
Just to follow up - this worked fine. The only bummer is that NSLog output stops appearing on the console after calling freopen, but it's a pretty minor issue.Twocolor
You can use isatty() to check if STDERR_FILENO is attached to a tty or not and choose not to redirect to file. It will be when you run the app via Xcode (or when its attached to the debugger, I guess). That's probably the only time you need the console output.Branle
@BenGottlieb Will using freopen in production cause mine app to be rejected?Chaparro
J
32

If you want to use Cocoa, NSString and NSData have methods for reading/writing to file and NSFileManager gives you file operations. Here's an example (should work on iPhone):

NSData *dataToWrite = [[NSString stringWithString:@"String to write"] dataUsingEncoding:NSUTF8StringEncoding];

NSString *docsDirectory = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) objectAtIndex:0];
NSString *path = [docsDirectory stringByAppendingPathComponent:@"fileName.txt"];

// Write the file
[dataToWrite writeToFile:path atomically:YES];

// Read the file
NSString *stringFromFile = [[NSString alloc] initWithContentsOfFile:path];  

// Check if file exists
NSFileManager *fileManager = [NSFileManager defaultManager];
[fileManager fileExistsAtPath:path]; // Returns a BOOL    

// Remove the file
[fileManager removeItemAtPath:path error:NULL];

// Cleanup
[stringFromFile release];
[fileManager release];
Josefina answered 15/10, 2008 at 2:43 Comment(0)
A
18

I've successfully used freopen(...) on the phone to re-direct output to my own file.

Anthropomorphize answered 14/10, 2008 at 18:52 Comment(5)
Do you remember which arguments you used?Twocolor
I used freopen([newFileName UTF8String], "w+", stderr), which redirected all console output to logFileName.Anthropomorphize
Just to follow up - this worked fine. The only bummer is that NSLog output stops appearing on the console after calling freopen, but it's a pretty minor issue.Twocolor
You can use isatty() to check if STDERR_FILENO is attached to a tty or not and choose not to redirect to file. It will be when you run the app via Xcode (or when its attached to the debugger, I guess). That's probably the only time you need the console output.Branle
@BenGottlieb Will using freopen in production cause mine app to be rejected?Chaparro
N
14

This code works great for me..

#if TARGET_IPHONE_SIMULATOR == 0
    NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
    NSString *documentsDirectory = [paths objectAtIndex:0];
    NSString *logPath = [documentsDirectory stringByAppendingPathComponent:@"console.log"];
    freopen([logPath cStringUsingEncoding:NSASCIIStringEncoding],"a+",stderr);
#endif

You can then get the log file off the iphone using the method outlined here http://blog.coriolis.ch/2009/01/09/redirect-nslog-to-a-file-on-the-iphone/#more-85

Note that using freopen will STOP THE CONSOLE IN XCODE working.. however, for some reason the console you can view in xcode's organiser still works great.

Nardone answered 20/1, 2010 at 16:38 Comment(1)
I've been able to work around the Xcode issue but only redirecting if the app is NOT running from Xcode by checking an environment variable of my choosing, set by Xcode. lists.apple.com/archives/xcode-users/2009/Aug/msg00507.html For example: if (getenv("MY_ENV_VAR") == NULL) { /* call freopen() */ }Madeleinemadelena
P
11

This code works for me:

- (void)applicationDidFinishLaunching:(UIApplication *)application {
#if TARGET_IPHONE_SIMULATOR == 0
    freopen([@"/tmp/my_logs.txt" fileSystemRepresentation], "w", stderr);
#endif
}
Palgrave answered 26/1, 2009 at 11:56 Comment(0)
V
3

Consider using Cocoa Lumberjack. It's a light but flexible utility to replace NSLog functionality. In my opinion it's in the same class as Log4J, allowing for custom appenders and the like. It has an SQLite logger, for example.

Violoncellist answered 28/12, 2011 at 15:44 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.