David Potter
David Potter

Reputation: 2302

Write stderr on iPhone to both file and console

I'm following the suggestion in the answer here for redirecting NSLog output on an iOS device to a file, which works great. The problem is that it no longer shows up in the console on the device. What I'd really like is a way to tee the stderr stream to both the console and the file. Does anyone have an idea how to do that?

Upvotes: 11

Views: 6146

Answers (3)

driedler
driedler

Reputation: 4190

Or you can redirect to a TCP socket and view on a remote telnet client. No need for XCode this way!

Basically:

  1. Create a standard C function which calls an Obj-C static method:

    void tcpLogg_log(NSString* fmt, ...)
    {
        va_list args;
        va_start(args, fmt);
        [TCPLogger tcpLog:fmt :args];
        va_end(args);
    }
    
  2. The static Obj-C method:

    (void)tcpLog:(NSString*)fmt :(va_list)args
    {
        NSLogv(fmt, args);
    
    
    if(sharedSingleton != nil && sharedSingleton.socket  != nil)
    {
      NSString *time = [sharedSingleton.dateFormat stringFromDate:[NSDate date]];
      NSString *msg = [[NSString alloc] initWithFormat:fmt arguments:args];
      mach_port_t tid = pthread_mach_thread_np(pthread_self());
    
      NSString *str = [NSString stringWithFormat:@"%@[%X]: %@\r\n", time, tid, msg];
      NSData *data = [str dataUsingEncoding:NSUTF8StringEncoding];
      [sharedSingleton.socket writeData:data 
                              withTimeout:NETWORK_CLIENT_TIMEOUT_PERIOD 
                              tag:0];                                                
    }
    
    }
  3. Then in your .pch file, add the following lines to override NSLog()

    define NSLog(...) tcpLogg_log(__VA_ARGS__); 
    void tcpLogg_log(NSString* fmt, ...);
    

Of course more details are required to handle the TCP Socket. Working source code is available here: https://github.com/driedler/iOS-TCP-Logger/wiki/About

Upvotes: 1

David Potter
David Potter

Reputation: 2302

I found an acceptable answer on another thread (NSLog() to both console and file).

The solution provided there is to only redirect to a file if a debugger is not detected, like this:

if (!isatty(STDERR_FILENO))
{
    // Redirection code
}

Thanks to Sailesh for that answer.

Upvotes: 10

QED
QED

Reputation: 9923

Once you freopen() the file descriptor, you can read from it and do as you please with the data. Some ideas from this will be useful to you.

You could either write it back out to stdout, or try to write directly to /dev/console. I've never tried to open /dev/console on an iPhone, but I'm guessing it's possible despite being outside of the sandbox. I'm not sure how the app review process will treat it.

Upvotes: 1

Related Questions