方法一
说明
在Objective-c开发程序的时候,有专门的日志操作类NSLog,它将指定的输出,输出到(stderr),我们可以利用Xcode的日志输出窗口,那么既然是要记录到具体日志文件,我们就想输出日志写入到具体的日志文件即可。
代码
1、
也就是说只有在DEBUG模式下才让日志输出 :)
#ifdef
#
#
#
#
#
#else
#
#
#
#
#
#endif
可以看到,除了标准的用户定义输出外,我还加入了许多有用的信息,
比如源程序文件位置,行号,类名,函数名等。具体的应用可以在具体的开发过程中添加、删除。
2、
-
}
-
}
}
真机测试的时候,可以利用freopen将标准错误输出保存到指定的文件当中,
这样就可以在问题发生后分析日志文件。
Xcode 一般会在 debug 运行配置项里面已经定义号了DEBUG 标志,如果没定义我们就自己写上,以我的 Xcode 4 为例,在项目get Info中找到 PreProcessor Macros 这个属性,对于 Debug 配置我们给他写上 DEBUG,而在 Release 配置中把它留空。 这样我们刚才那段预处理命令就可以根据这个标志来判断我们编译的时调试版本还是发布版本,从而控制 NSLog 的输出。 (因为 Xcode 4会把 debug/release 两个配置项同时对比展现出来,而 3.x 版本的只能分别设置,如果你用的时xcode 3.x 开发工具, 那么就分别对 Debug/Release 都检查一下)。
其他
方法二
iOS - NSLog、UncaughtException日志保存到文件
对于真机,日志没法保存,不好分析问题。所以有必要将日志保存到应用的Docunment目录下,方便取出分析。
首先是日志输出,分为c的printf和标准的NSLog输出,printf会向标准输出(sedout)打印,而NSLog则是向标准出错(stderr),我们需要同时让他们都将日志打印到一个文件中。
我写了两个函数用于写NSLog日志和Crash日志,这个两个函数都必须在AppDelegate文件中下面的函数里添加
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOp
- //连接xcode时可以从监视器中看日志
没连接时Log日志会输出到文件中, - [self
redirectNSLogToDocumentF older];
- -
(void)redirectNSLogToDocumentF older - {
-
//如果已经连接Xcode调试则不输出到文件 -
if(isatty(STDOUT_FILENO)) { -
return; -
} -
-
UIDevice *device = [UIDevice currentDevice]; -
if([[device model] hasSuffix:@"Simulator"]){ //在模拟器不保存到文件中 -
return; -
} -
-
//将NSlog打印信息保存到Document目录下的Log文件夹下 -
NSArray *paths = NSSearchPathForDirectori esInDomains(NSDocumentDirectory, NSUserDomainMask, YES); -
NSString *logDirectory = [[paths objectAtIndex:0] stringByAppendingPathCom ponent:@"Log"]; -
-
NSFileManager *fileManager = [NSFileManager defaultManager]; -
BOOL fileExists = [fileManager fileExistsAtPath:logDirectory]; -
if (!fileExists) { -
[fileManager createDirectoryAtPath:logDirectory withIntermediateDirector ies: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异常日志 -
NSSetUncaughtExceptionHa ndler (&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 = NSSearchPathForDirectori esInDomains(NSDocumentDirectory, NSUserDomainMask, YES); -
NSString *logDirectory = [[paths objectAtIndex:0] stringByAppendingPathCom ponent:@"Log"]; -
-
NSFileManager *fileManager = [NSFileManager defaultManager]; -
if (![fileManager fileExistsAtPath:logDirectory]) { -
[fileManager createDirectoryAtPath:logDirectory withIntermediateDirector ies:YES attributes:nil error:nil]; -
} -
-
NSString *logFilePath = [logDirectory stringByAppendingPathCom ponent:@"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 fileHandleForWritingAtPa th:logFilePath]; -
[outFile seekToEndOfFile]; -
[outFile writeData:[crashString dataUsingEncoding:NSUTF8StringEncoding]]; -
[outFile closeFile]; -
} -
-
//把错误日志发送到邮箱 -
// NSString *urlStr = [NSString stringWithFormat:@"mailto://test@163.com?subject=bug报告&body=感谢您的配合!
错误详情:
%@",crashString]; -
// NSURL *url = [NSURL URLWithString:[urlStr stringByAddingPercentEsc apesUsingEncoding:NSUTF8StringEncoding]]; -
// [[UIApplication sharedApplication] openURL:url]; - }