之前博客介绍啦一种异常捕获后弹窗提示用户的方法,《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