In daily work, the log is an indispensable link, usually their own debugging, can be directly connected to the computer, directly in the window to view the results.

But how do you get the logs when testers are testing, or grayscale testing? The first thing to think about is exporting to a local file and then uploading as needed.

To share a previously found method, the following code provides two main functions:

  • Output the log to a file
  • Catching exception Information

[The explanation is written in the comments]


- (void)redirectNSLogToDocumentFolder
{
// No output to file if Xcode debugging is already connected
// This function is used to check if output (STDOUT_FILENO) is redirected as a Linux program method
if(isatty(STDOUT_FILENO)) {  
    return;
}

// Check whether the current emulator environment does not save to the file in the emulator
UIDevice *device = [UIDevice currentDevice];
if([[device model] hasSuffix:@"Simulator"]) {return;
}

// Save the NSlog print information to the Log folder in the Document directory
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *logDirectory = [[paths objectAtIndex:0] stringByAppendingPathComponent:@"Log"];

NSFileManager *fileManager = [NSFileManager defaultManager];
BOOL fileExists = [fileManager fileExistsAtPath:logDirectory];
if(! fileExists) { [fileManager createDirectoryAtPath:logDirectory withIntermediateDirectories:YES attributes:nil error:nil];  } NSDateFormatter *formatter = [[NSDateFormatter alloc] init]; [formatter setLocale:[[NSLocale alloc] initWithLocaleIdentifier:@"zh_CN"]];
[formatter setDateFormat:@"yyyy-MM-dd HH:mm:ss"]; // Save a new log file after each startup
NSString *dateStr = [formatter stringFromDate:[NSDate date]];
NSString *logFilePath = [logDirectory stringByAppendingFormat:@"/%@.log",dateStr];

// Enter log into the file
freopen([logFilePath cStringUsingEncoding:NSUTF8StringEncoding], "a+", stdout);
freopen([logFilePath cStringUsingEncoding:NSUTF8StringEncoding], "a+", stderr);

// Uncaught Objective-C exception logs
NSSetUncaughtExceptionHandler (&UncaughtExceptionHandler);
}Copy the code

Look before, for NSSetUncaughtExceptionHandler (& UncaughtExceptionHandler) a little knowledge, the usage to the source code, this method is in the Foundation.

Sets the top-level error-handling function where you can perform last-minute logging before the program terminates. By replacing the top-level handle method, the crash information can be retrieved and performed before the program terminates, such as saving locally or reporting.

Method calls for: void NSSetUncaughtExceptionHandler (NSUncaughtExceptionHandler *);

The incoming is a NSUncaughtExceptionHandler pointer.

typedef void NSUncaughtExceptionHandler(NSException *exception);

A pointer to a void function with NSException *exception is required.

You want it, I’ll give it to you!

So here’s a C function, and you can see that this is written differently than the OC declaration.

void UncaughtExceptionHandler(NSException* exception)
{
    NSString* name = [ exception name ];
    NSString* reason = [ exception reason ];
    NSArray* symbols = [ exception callStackSymbols ]; // Call stack when an exception occurs
    NSMutableString* strSymbols = [ [ NSMutableString alloc ] init ]; // Assemble the call stack into a string to output the log
    for ( NSString* item in symbols )
    {
        [ strSymbols appendString: item ];
        [ strSymbols appendString: @"\r\n" ];
    }

    // Save crash logs to the Log folder in the Document directory
    NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
    NSString *logDirectory = [[paths objectAtIndex:0] stringByAppendingPathComponent:@"Log"];

    NSFileManager *fileManager = [NSFileManager defaultManager];
    if(! [fileManager fileExistsAtPath:logDirectory]) { [fileManager createDirectoryAtPath:logDirectory withIntermediateDirectories:YES attributes:nil error:nil]; } NSString *logFilePath = [logDirectory stringByAppendingPathComponent:@"UncaughtException.log"];
    NSDateFormatter *formatter = [[NSDateFormatter alloc] init];
    [formatter setLocale:[[NSLocale alloc] initWithLocaleIdentifier:@"zh_CN"]];
    [formatter setDateFormat:@"yyyy-MM-dd HH:mm:ss"];
    NSString *dateStr = [formatter stringFromDate:[NSDate date]];

    NSString *crashString = [NSString stringWithFormat:@"<- %@ ->[ Uncaught Exception ]\r\nName: %@, Reason: %@\r\n[ Fe Symbols Start ]\r\n%@[ Fe Symbols End ]\r\n\r\n", dateStr, name, reason, strSymbols];
    // Write error log to file
    if(! [fileManager fileExistsAtPath:logFilePath]) { [crashString writeToFile:logFilePath atomically:YES encoding:NSUTF8StringEncoding error:nil]; }else{
        NSFileHandle *outFile = [NSFileHandle fileHandleForWritingAtPath:logFilePath];
        [outFile seekToEndOfFile];
        [outFile writeData:[crashString dataUsingEncoding:NSUTF8StringEncoding]];
        [outFile closeFile];
    }

    // Send the error log to the mailbox
    // NSString *urlStr = [NSString stringWithFormat:@"mailto://[email protected]? Subject =bug report &body= Thank you for your help! 

%@",crashString];
// NSURL *url = [NSURL URLWithString:[urlStr stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding]]; // [[UIApplication sharedApplication] openURL:url]; }Copy the code