日志文件保存到Document

来源:互联网 发布:淄博市网络教研平台 编辑:程序博客网 时间:2024/04/29 23:12

方法一

说明

Objective-c开发程序的时候,有专门的日志操作类NSLog,它将指定的输出,输出到(stderr,我们可以利用Xcode的日志输出窗口,那么既然是要记录到具体日志文件,我们就想输出日志写入到具体的日志文件即可。

 

代码

1  宏定义(下面是我在程序中常用到的日志宏,用DEBUG开关管理,

也就是说只有在DEBUG模式下才让日志输出 :)

 

#ifdef DEBUG  

 define LOG(fmt, ...) do                                            \  

        NSString* file [[NSString alloc] initWithFormat:@"%s", __FILE__]; \  

        NSLog((@"%@(%d) fmt), [file lastPathComponent], __LINE__, ##__VA_ARGS__); \  

        [file release];                                                 \  

    while(0)  

 define LOG_METHOD NSLog(@"%s", __func__)  

 define LOG_CMETHOD NSLog(@"%@/%@", NSStringFromClass([self class]), NSStringFromSelector(_cmd))  

 define COUNT(p) NSLog(@"%s(%d): count %d\n", __func__, __LINE__, [p retainCount]);  

 define LOG_TRACE(x) do {printf x; putchar('\n'); fflush(stdout);} while (0)  

#else  

 define LOG(...)  

 define LOG_METHOD  

 define LOG_CMETHOD  

 define COUNT(p)  

 define LOG_TRACE(x)  

#endif

 

可以看到,除了标准的用户定义输出外,我还加入了许多有用的信息,

比如源程序文件位置,行号,类名,函数名等。具体的应用可以在具体的开发过程中添加、删除。

 

2  应用

(void)redirectNSLogToDocumentFolder{  

    NSArray *paths NSSearchPathForDirectoriesInDomains(NSDocumentDirectory,NSUserDomainMask, YES);  

    NSString *documentsDirectory [paths objectAtIndex:0];  

    NSString *fileName =[NSString stringWithFormat:@"%@.log",[NSDate date]];  

    NSString *logFilePath [documentsDirectory stringByAppendingPathComponent:fileName];  

    freopen([logFilePath cStringUsingEncoding:NSASCIIStringEncoding],"a+",stderr);  

}  

 

(void)applicationDidFinishLaunching:(UIApplication *)application {  

    // 真机测试时保存日志  

    if ([CDeviceInfo getModelType] != SIMULATOR) {  

        [self redirectNSLogToDocumentFolder];  

}  

}

 

真机测试的时候,可以利用freopen将标准错误输出保存到指定的文件当中,

这样就可以在问题发生后分析日志文件。

 3  设置DEBUG标志是否正确定义

 

Xcode 一般会在 debug 运行配置项里面已经定义号了DEBUG 标志,如果没定义我们就自己写上,以我的 Xcode 4 为例,在项目get Info中找到 PreProcessor Macros 这个属性,对于 Debug 配置我们给他写上 DEBUG,而在 Release 配置中把它留空。 这样我们刚才那段预处理命令就可以根据这个标志来判断我们编译的时调试版本还是发布版本,从而控制 NSLog 的输出。 (因为 Xcode 4会把 debug/release 两个配置项同时对比展现出来,而 3.x 版本的只能分别设置,如果你用的时xcode 3.x 开发工具, 那么就分别对 Debug/Release 都检查一下)

 

其他

               来源:

               iPhone开发技巧之日志保存教程

               iPhone应用根据DebugRelease状态变化来屏蔽日志输出

方法二

iOS - NSLog、UncaughtException日志保存到文件

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


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


    错误详情:
    %@",crashString ];  
  77.     //    NSURL *url [NSURL URLWithString:[urlStr stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding]];  
  78.     //    [[UIApplication sharedApplication] openURL:url];  
  79.  
0 0
原创粉丝点击