之前博客介绍啦一种异常捕获后弹窗提示用户的方法,《iOS崩溃 捕获异常处理》,下面提供另外一种异常捕获的方法。原理一致,但实现略有不同。可供参考。
1、在didFinishLaunchingWithOptions 中,注册消息处理函数,处理崩溃信息,写入本地。
NSSetUncaughtExceptionHandler(&uncaughtExceptionHandler);
2、将CrashManager.h、 CrashManager.m 拖拽到工程中,具体实现如下:
CrashManager.h:
@interface CrashManager : NSObject
/** 捕捉Crash */
void uncaughtExceptionHandler(NSException *exception);
+ (id)defaultManager;
/** 移除Crash的log日志 */
- (void)clearCrashLog;
/** 是否有log日志 */
- (BOOL)isCrashLog;
/** crash log日志 */
- (NSString *)crashLogContent;
@end
CrashManager.m 中核心函数如下:
void uncaughtExceptionHandler(NSException *exception){
NSArray *stackArray = [exception callStackSymbols];
NSString *reason = [exception reason];
NSString *name = [exception name];
NSString *exceptionInfo = [NSString stringWithFormat:@"Exception reason:%@\nException name:%@\nException stack:%@",name, reason, stackArray];
NSLog(@"%@", exceptionInfo);
NSMutableArray *tmpArr = [NSMutableArray arrayWithArray:stackArray];
[tmpArr insertObject:reason atIndex:0];
NSString *crashLocalPath = [NSString stringWithFormat:@"%@/Documents/microFinanceCrashError.txt",NSHomeDirectory()];
NSLog(@"crash LocalPath :%@ ",crashLocalPath);
[exceptionInfo writeToFile:crashLocalPath atomically:YES encoding:NSUTF8StringEncoding error:nil];
}
+ (id)defaultManager{
@synchronized(self){
static dispatch_once_t pred;
dispatch_once(&pred, ^{
crashManager = [[self alloc] init];
});
}
return crashManager;
}
#pragma mark -移除Crash的log日志
- (void)clearCrashLog{
NSFileManager *fileManager = [[NSFileManager alloc]init];
[fileManager removeItemAtPath:LocalCrashLogPath error:nil];
}
#pragma mark - 是否有log日志
- (BOOL)isCrashLog{
NSError *error;
NSString *textFileContents = [NSString stringWithContentsOfFile:LocalCrashLogPath encoding:NSUTF8StringEncoding error:&error];
if ([self checkConvertNull:textFileContents]) {
return NO;
}else{
return YES;
}
}
#pragma mark -crash log日志
- (NSString *)crashLogContent{
NSError *error;
NSString *textFileContents = [NSString stringWithContentsOfFile:LocalCrashLogPath encoding:NSUTF8StringEncoding error:&error];
if ([self checkConvertNull:textFileContents]) {
return @"";
}else{
return textFileContents;
}
}
#pragma mark - 检查是否有空字符
- (BOOL)checkConvertNull:(NSString *)object{
if ([object isEqual:[NSNull null]] || [object isKindOfClass:[NSNull class]] ||object==nil || [object isEqualToString:@""]) {
return YES;
}else{
return NO;
}
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
3、在ViewController中,做如下测试案例:
- (void)viewDidLoad {
[super viewDidLoad];
CrashManager *crashManager = [CrashManager defaultManager];
if ([crashManager isCrashLog]) {
NSString *crashString = [crashManager crashLogContent];
NSLog(@"crashString = %@",crashString);
}
UIButton *crashBtn = [UIButton buttonWithType:UIButtonTypeCustom];
crashBtn.frame = CGRectMake(self.view.frame.size.width/2 - 50, 200, 100, 40);
crashBtn.backgroundColor = [UIColor redColor];
[crashBtn addTarget:self action:@selector(crashTest) forControlEvents:UIControlEventTouchUpInside];
[crashBtn setTitle:@"Crash" forState:UIControlStateNormal];
[crashBtn setTitleColor:[UIColor blackColor] forState:UIControlStateNormal];
[self.view addSubview:crashBtn];
}
-(void)crashTest{
NSString *crashString = nil;
NSDictionary *params = [NSDictionary dictionary];
params = @{@"crashTest":crashString,
};
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
Demo地址:https://github.com/heroBlog/CrashManager