__VA_ARGS__ 是一个可变参数的宏,这个可变参数的宏是新的C99规范中新增的,目前似乎只有gcc支持(VC6.0的编译器不支持)。宏前面加上##的作用在于,当可变参数的个数为0时,这里的##起到把前面多余的","去掉的作用,否则会编译出错
__FILE__ %s 宏在预编译时会替换成当前的源文件名,当前源代码文件全路径
__FUNCTION__宏在预编译时会替换成当前的函数名称
__func__%s 当前函数签名
__LINE__ %d 在源代码文件中当前所在行数,宏在预编译时会替换成当前的行号
__PRETTY_FUNCTION__ %s 像 __func__,但是包含了C++代码中的隐形类型信息
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions{ //连接xcode时可以从监视器中看日志 没连接时Log日志会输出到文件中, [self redirectNSLogToDocumentFolder]; return YES; } - (void)redirectNSLogToDocumentFolder { //如果已经连接Xcode调试则不输出到文件 // if(isatty(STDOUT_FILENO)) { // return; // } // UIDevice *device = [UIDevice currentDevice]; // if([[device model] hasSuffix:@"Simulator"]){ //在模拟器不保存到文件中 // return; // } //将NSlog打印信息保存到Document目录下的Log文件夹下 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"]; //每次启动后都保存一个新的日志文件中 NSString *dateStr = [formatter stringFromDate:[NSDate date]]; NSString *logFilePath = [logDirectory stringByAppendingFormat:@"/%@.log",dateStr]; // 将log输入到文件 freopen([logFilePath cStringUsingEncoding:NSASCIIStringEncoding], "a+", stdout); freopen([logFilePath cStringUsingEncoding:NSASCIIStringEncoding], "a+", stderr); //未捕获的Objective-C异常日志 NSSetUncaughtExceptionHandler (&UncaughtExceptionHandler); } void UncaughtExceptionHandler(NSException* exception) { NSString* name = [ exception name ]; NSString* reason = [ exception reason ]; NSArray* symbols = [ exception callStackSymbols ]; // 异常发生时的调用栈 NSMutableString* strSymbols = [ [ NSMutableString alloc ] init ]; //将调用栈拼成输出日志的字符串 for ( NSString* item in symbols ) { [ strSymbols appendString: item ]; [ strSymbols appendString: @"\r\n" ]; } //将crash日志保存到Document目录下的Log文件夹下 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]; //把错误日志写到文件中 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]; } //把错误日志发送到邮箱 // NSMutableString *mailUrl = [NSMutableString string]; // [mailUrl appendString:@"mailto:xxxxxxxxx@qq.com"]; // [mailUrl appendString:@"?subject=程序异常崩溃,请配合发送异常报告,谢谢合作!"]; // [mailUrl appendFormat:@"&body=%@", crashString]; // // 打开地址 //// NSString *mailPath = [mailUrl stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding]; // NSString *mailPath = [mailUrl stringByAddingPercentEncodingWithAllowedCharacters:[NSCharacterSet characterSetWithRange:NSMakeRange(0, mailUrl.length)]]; // [[UIApplication sharedApplication] openURL:[NSURL URLWithString:mailPath]]; }