转:http://blog.csdn.net/marujunyy/article/details/12005767

对于真机,日志没法保存,不好分析问题。所以有必要将日志保存到应用的Docunment目录下,方便取出分析。

首先是日志输出,分为c的printf和标准的NSLog输出,printf会向标准输出(sedout)打印,而NSLog则是向标准出错(stderr),我们需要同时让他们都将日志打印到一个文件中。 其次是Crash问题;Crash分为两种,一种是由EXC_BAD_ACCESS引起的,原因是访问了不属于本进程的内存地址,有可能是访问已被释放的内存;另一种是未被捕获的Objective-C异常(NSException),导致程序向自身发送了SIGABRT信号而崩溃。其实对于未捕获的Objective-C异常,我们是有办法将它记录下来的,如果日志记录得当,能够解决绝大部分崩溃的问题。

我写了两个函数用于写NSLog日志和Crash日志,这个两个函数都必须在AppDelegate文件中下面的函数里添加

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions

  1. //连接xcode时可以从监视器中看日志 没连接时Log日志会输出到文件中,
  2. [self redirectNSLogToDocumentFolder];
  1. - (void)redirectNSLogToDocumentFolder
  2. {
  3. //如果已经连接Xcode调试则不输出到文件
  4. if(isatty(STDOUT_FILENO)) {
  5. return;
  6. }
  7. UIDevice *device = [UIDevice currentDevice];
  8. if([[device model] hasSuffix:@"Simulator"]){ //在模拟器不保存到文件中
  9. return;
  10. }
  11. //将NSlog打印信息保存到Document目录下的Log文件夹下
  12. NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
  13. NSString *logDirectory = [[paths objectAtIndex:0] stringByAppendingPathComponent:@"Log"];
  14. NSFileManager *fileManager = [NSFileManager defaultManager];
  15. BOOL fileExists = [fileManager fileExistsAtPath:logDirectory];
  16. if (!fileExists) {
  17. [fileManager createDirectoryAtPath:logDirectory  withIntermediateDirectories:YES attributes:nil error:nil];
  18. }
  19. NSDateFormatter *formatter = [[NSDateFormatter alloc] init];
  20. [formatter setLocale:[[NSLocale alloc] initWithLocaleIdentifier:@"zh_CN"]];
  21. [formatter setDateFormat:@"yyyy-MM-dd HH:mm:ss"]; //每次启动后都保存一个新的日志文件中
  22. NSString *dateStr = [formatter stringFromDate:[NSDate date]];
  23. NSString *logFilePath = [logDirectory stringByAppendingFormat:@"/%@.log",dateStr];
  24. // 将log输入到文件
  25. freopen([logFilePath cStringUsingEncoding:NSASCIIStringEncoding], "a+", stdout);
  26. freopen([logFilePath cStringUsingEncoding:NSASCIIStringEncoding], "a+", stderr);
  27. //未捕获的Objective-C异常日志
  28. NSSetUncaughtExceptionHandler (&UncaughtExceptionHandler);
  29. }
  30. void UncaughtExceptionHandler(NSException* exception)
  31. {
  32. NSString* name = [ exception name ];
  33. NSString* reason = [ exception reason ];
  34. NSArray* symbols = [ exception callStackSymbols ]; // 异常发生时的调用栈
  35. NSMutableString* strSymbols = [ [ NSMutableString alloc ] init ]; //将调用栈拼成输出日志的字符串
  36. for ( NSString* item in symbols )
  37. {
  38. [ strSymbols appendString: item ];
  39. [ strSymbols appendString: @"\r\n" ];
  40. }
  41. //将crash日志保存到Document目录下的Log文件夹下
  42. NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
  43. NSString *logDirectory = [[paths objectAtIndex:0] stringByAppendingPathComponent:@"Log"];
  44. NSFileManager *fileManager = [NSFileManager defaultManager];
  45. if (![fileManager fileExistsAtPath:logDirectory]) {
  46. [fileManager createDirectoryAtPath:logDirectory  withIntermediateDirectories:YES attributes:nil error:nil];
  47. }
  48. NSString *logFilePath = [logDirectory stringByAppendingPathComponent:@"UncaughtException.log"];
  49. NSDateFormatter *formatter = [[NSDateFormatter alloc] init];
  50. [formatter setLocale:[[NSLocale alloc] initWithLocaleIdentifier:@"zh_CN"]];
  51. [formatter setDateFormat:@"yyyy-MM-dd HH:mm:ss"];
  52. NSString *dateStr = [formatter stringFromDate:[NSDate date]];
  53. 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];
  54. //把错误日志写到文件中
  55. if (![fileManager fileExistsAtPath:logFilePath]) {
  56. [crashString writeToFile:logFilePath atomically:YES encoding:NSUTF8StringEncoding error:nil];
  57. }else{
  58. NSFileHandle *outFile = [NSFileHandle fileHandleForWritingAtPath:logFilePath];
  59. [outFile seekToEndOfFile];
  60. [outFile writeData:[crashString dataUsingEncoding:NSUTF8StringEncoding]];
  61. [outFile closeFile];
  62. }
  63. //把错误日志发送到邮箱
  64. //    NSString *urlStr = [NSString stringWithFormat:@"mailto://test@163.com?subject=bug报告&body=感谢您的配合!<br><br><br&gt;错误详情:<br>%@",crashString ];
  65. //    NSURL *url = [NSURL URLWithString:[urlStr stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding]];
  66. //    [[UIApplication sharedApplication] openURL:url];
  67. }

iOS - NSLog、UncaughtException日志保存到文件的更多相关文章

  1. 【代码笔记】iOS-将log日志保存到文件

    代码: #import "AppDelegate.h" #import "RootViewController.h" @implementation AppDe ...

  2. logstash自己的日志保存到文件中:log4j2.properties

    status = error dest = err name = PropertiesConfig property.filename = /gwlog/data/logstash/logs appe ...

  3. C# log4net 配置及使用详解--日志保存到文件和Access(转)

    按语: 最近项目要求选用Access数据库,但日志管理采用log4net,但保存到数据库一直没有成功,后按照如下配置在程序退出时可以成功保存. 开始新建文件应用log4net.dll  ,重新编译就报 ...

  4. ios NSLog常见使用

    NSLog常见输出格式 Table 1  Format specifiers supported by the NSString formatting methods and CFString for ...

  5. 如何将Log4Net 日志保存到mongodb数据库之实践

    log4net的大名早有耳闻,一直没真正用过,这次开发APP项目准备在服务端使用log4net. 日志的数据量较大,频繁的写数据库容易影响系统整体性能,所以独立将日志写到mongodb数据库是不错的选 ...

  6. iOS - NSLog的使用方法

    NSLog的定义 NSLog定义在NSObjCRuntime.h中,如下所示: void NSLog(NSString *format, …); 基本上,NSLog很像printf,同样会在conso ...

  7. IOS NSLog 打印bool值

    输出BOOL值的方法:NSLog(@"%@",YES?@"YES":@"NO");%@输出字符串. NSLog(@"ifReadO ...

  8. iOS NSLog去掉时间戳及其他输出样式

    1.一般项目中我的NSLog会在Prefix.pch文件添加如下代码,已保证在非调试状态下NSLog不工作   1 2 3 4 5 #ifdef DEBUG #define NSLog(...) NS ...

  9. iOS NSLog各种打印

    %@ 对象 %d,%i 整型 (%i的老写法) %hd 短整型 %ld , %lld 长整型 %u 无符整型 %f 浮点型和double型 %0.2f 精度浮点数,只保留两位小数 %x:    为32 ...

随机推荐

  1. Codeforces 337D Book of evil

    一道树形dp,写出来是因为最近也做了道类似的.这题是看了分析的思路才做出来的,但感觉很多这样的dp都是利用类似的性质.像这题的话distDown很好想,但distUp的时候就很难想了,其实只要抓住di ...

  2. ****Git 常用命令和使用思维导图

    Git 是一个很强大的分布式版本控制系统.它不但适用于管理大型开源软件的源代码,管理私人的文档和源代码也有很多优势. 本来想着只把最有用.最常用的 Git 命令记下来,但是总觉得这个也挺有用.那个也用 ...

  3. Oracle导出空表(从来都没有用过的表)

    Oracle11g默认对空表不分配segment,故使用exp导出Oracle11g数据库时,空表不会导出! .设置deferred_segment_creation参数为FALSE后,无论是空表还是 ...

  4. 关于in与exists的效率讨论

    关于in与exists的效率讨论1).select * from A where id in (select id from B)以上查询使用了in语句,in只执行一次,他查出B表的所有id字段并缓存 ...

  5. 欧拉工程第67题:Maximum path sum II

    By starting at the top of the triangle below and moving to adjacent numbers on the row below, the ma ...

  6. Apache 下SVN项目管理使用说明

    Apache 下SVN项目管理使用说明 (1)Apaceh和SVN先要装好. (2)在apache的目录下找到httpd.conf文件,在最后一行增加如下配置 Include conf/svn.pro ...

  7. Android LayoutInflater.inflate()的参数及其用法

    很多人在网上问LayoutInflater类的用法,以及inflate()方法参数的含义,现解释如下: inflate()的作用就是将一个用xml定义的布局文件查找出来,注意与findViewById ...

  8. KMP算法的C++实现

    这个问题阮一峰老师讲的很清楚,链接 这里我只贴一下我的C++实现代码: #include <iostream> #include <cstring> #include < ...

  9. Hadoop HDFS文件常用操作及注意事项(更新)

    1.Copy a file from the local file system to HDFS The srcFile variable needs to contain the full name ...

  10. JVM学习笔记(二)------Java代码编译和执行的整个过程

    Java代码编译是由Java源码编译器来完成,流程图如下所示: Java字节码的执行是由JVM执行引擎来完成,流程图如下所示: Java代码编译和执行的整个过程包含了以下三个重要的机制: Java源码 ...