iOS崩溃日志打印出来或者写进文件
2014-02-14 14:17
465 查看
对于真机,日志没法保存,不好分析问题。所以有必要将日志保存到应用的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
//连接xcode时可以从监视器中看日志 没连接时Log日志会输出到文件中,
[self redirectNSLogToDocumentFolder];
- (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];
BOOL fileExists = [fileManager fileExistsAtPath:logDirectory];
if (!fileExists) {
[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 ]", dateStr, name, reason, strSymbols];
//把错误日志写到文件中
freopen([logFilePath cStringUsingEncoding:NSASCIIStringEncoding], "a+", (__bridge FILE *)(crashString));
//把错误日志发送到邮箱
// NSString *urlStr = [NSString stringWithFormat:@"mailto://test@163.com?subject=bug报告&body=感谢您的配合!<br><br><br>错误详情:<br>%@",crashString ];
// NSURL *url = [NSURL URLWithString:[urlStr stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding]];
// [[UIApplication sharedApplication] openURL:url];
}
首先是日志输出,分为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
//连接xcode时可以从监视器中看日志 没连接时Log日志会输出到文件中,
[self redirectNSLogToDocumentFolder];
- (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];
BOOL fileExists = [fileManager fileExistsAtPath:logDirectory];
if (!fileExists) {
[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 ]", dateStr, name, reason, strSymbols];
//把错误日志写到文件中
freopen([logFilePath cStringUsingEncoding:NSASCIIStringEncoding], "a+", (__bridge FILE *)(crashString));
//把错误日志发送到邮箱
// NSString *urlStr = [NSString stringWithFormat:@"mailto://test@163.com?subject=bug报告&body=感谢您的配合!<br><br><br>错误详情:<br>%@",crashString ];
// NSURL *url = [NSURL URLWithString:[urlStr stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding]];
// [[UIApplication sharedApplication] openURL:url];
}
相关文章推荐
- Ios自定义日志打印以及捕捉崩溃日志并存入文件
- iOS 将崩溃Log日志重定向输出到文件中保存
- iOS--上线被拒如何从苹果返回的崩溃日志iOS.crash文件处理找崩点(看这篇就懂了)
- iOS 将崩溃Log日志重定向输出到文件中保存
- 苹果审核返回崩溃日志 iOS .crash文件处理 symbolicatecrash
- iOS 开发 Pch 文件的正确使用1.存放一些全局的宏(整个项目中都用得上的宏) 2.用来包含一些全部的头文件(整个项目中都用得上的头文件) 3.能自动打开或者关闭日志输出功能
- 【iOS开发问题】使用NSCoding写入本地文件读取不出来或者文件没有写入本地
- 使用dSYM 文件分析iOS崩溃日志
- ios 日志信息打印到文件中
- linux网络监控工具---系统自带的工具的使用示例(可以监控经过本局域网的任何数据,并可以打印到屏幕或者日志文件)
- ios记录日志和崩溃日志,并将日志文件发送到指定的邮箱
- iOS日常Debug之Crash日志文件分析
- 151223iOS应用崩溃日志分析 iOS应用崩溃日记揭秘
- 安卓程序运行中突然崩溃的时候打印日志到本地
- 电脑断电导致日志文件损坏或者只有mdf还原数据解决
- iOS崩溃日志
- iOS应用崩溃日志分析
- Log4j配置的经典总结,打印日志文件,日志存库
- iOS应用崩溃日志分析
- ios 'Can't add self as subview'崩溃日志详解