全局异常捕获对App开发和日常产品维护具有重要的意义,我们不可能在程序开发中做的极致,因此我们需要用户终端反馈异常信息。
在iOS中捕获全局异常需要有以下几种条件
1.实现全局钩子(默认异常处理句柄)
2.收集手机基础参数信息
3.打印异常堆栈信息
主要代码如下:
AppCatchExceptionHandler.h
@interface AppCatchExceptionHandler : NSObject
+ (void)setDefaultHandler;
+ (NSUncaughtExceptionHandler *)getUncaughtExceptionHandler;
@end
AppCatchExceptionHandler.m
#import <Foundation/Foundation.h>
#import "CatchExceptionHandler.h"
#define AppExceptionFile @"log_ErrorFile_%@.txt"
@implementation AppCatchExceptionHandler
NSString *applicationDocumentsDirectory() {
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask,YES);
NSString * documentsDirectory =[paths objectAtIndex:0];
NSDate* dat = [NSDate dateWithTimeIntervalSinceNow:0];
NSTimeInterval timeinterval =[dat timeIntervalSince1970]*1000;
NSString *timeString = [NSString stringWithFormat:@"%0.0f", timeinterval];//转为字符型
NSString *logFilename = = [NSString stringWidthFormat:AppExceptionFile,timeString];
return [documentsDirectory stringByAppendingPathComponent:logFilename ];
}
void UncaughtExceptionHandler(NSException *exception)
{
NSArray *arr = [exception callStackSymbols];
NSString *reason = [exception reason];
NSString *name = [exception name];
NSDate* dat = [NSDate dateWithTimeIntervalSinceNow:0];
NSTimeInterval timeinterval =[dat timeIntervalSince1970]*1000;
NSString *timeString = [NSString stringWithFormat:@"%0.0f", timeinterval];//转为字符型
NSString *strTime =timeString;
NSString *strError = [NSString stringWithFormat:@"\n\n\n=============异常崩溃报告=============\n当前版本的编译时间:\n%@\n崩溃发生的时间:\n %@\n崩溃名称:\n%@\n崩溃原因:\n%@\n堆栈信息:\n%@",timeString ,strTime,name,reason,[arr componentsJoinedByString:@"\n"]];
NSString *path = applicationDocumentsDirectory();
if ([[NSFileManager defaultManager]fileExistsAtPath:path])
{
NSString *lasterror = [[NSString alloc] initWithContentsOfFile:path encoding:NSUTF8StringEncoding error:nil];
strError = [NSString stringWithFormat:@"%@%@", lasterror, strError];
[lasterror release];
}
[strError writeToFile:path atomically:YES encoding:NSUTF8StringEncoding error:nil];
NSMutableString *mailUrl = [[[NSMutableString alloc]init]autorelease];
//添加收件人
NSArray *toRecipients = [NSArray arrayWithObjects: @"a@b.com", @"a@a.com",nil];
[mailUrl appendFormat:@"mailto:%@", [toRecipients componentsJoinedByString:@","]];
//添加抄送
NSArray *ccRecipients = [NSArray arrayWithObjects:@"e@e.com" ,nil];
[mailUrl appendFormat:@"?cc=%@", [ccRecipients componentsJoinedByString:@","]];
//添加密送
NSArray *bccRecipients = [NSArray arrayWithObjects:@"", nil];
[mailUrl appendFormat:@"&bcc=%@", [bccRecipients componentsJoinedByString:@","]];
[mailUrl appendString:@"&subject=崩溃日志"];
//添加邮件内容
[mailUrl appendString:[NSString stringWithFormat:@"&body=%@", strError]];
NSString* email = [mailUrl stringByAddingPercentEscapesUsingEncoding: NSUTF8StringEncoding];
//#ifdef _DEBUG_LOG_
[[UIApplication sharedApplication] openURL: [NSURL URLWithString:email]];
//#endif
}
+ (void)setDefaultHandler
{
NSSetUncaughtExceptionHandler (&UncaughtExceptionHandler);
}
+ (NSUncaughtExceptionHandler*)getUncaughtExceptionHandler
{
return NSGetUncaughtExceptionHandler();
}
@end
使用方式
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
[NSThread detachNewThreadSelector:@selector(setDefaultHandler) toTarget:AppCatchExceptionHandler withObject:nil];
return YES;
}