NSException
异常捕获
@try { // 代码逻辑 NSLog(@"方法正常执行"); } @catch (NSException *exception) { NSLog(@"代码有异常----%@", exception); } @finally { NSLog(@"不管方法是否出错这里的代码都会被执行"); }
抛出异常
@throw [NSException exceptionWithName:@"错误提示" reason:@"方法找不到" userInfo:nil]; // 这种方式更好一点 [NSException raise:@"错误提示" format:@"%@方法找不到", NSStringFromSelector(selector)];
崩溃统计分析
主流做法
/** * 拦截异常 */ void handleException(NSException *exception) { NSMutableDictionary *errorInfoDict = [NSMutableDictionary dictionaryWithContentsOfFile:YHErrorPath]; if(errorInfoDict == nil) { errorInfoDict = [NSMutableDictionary dictionary]; } // 调用栈信息(错误来源于哪个方法) errorInfoDict[@"callStack"] = [exception callStackSymbols]; // 异常名字 errorInfoDict[@"name"] = [exception name]; // 异常描述(报错理由) errorInfoDict[@"reason"] = [exception reason]; // 写入到文件中,下次程序启动时回传给服务器 [errorInfoDict writeToFile:YHErrorPath atomically:YES]; } - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { // 可以在应用启动时将沙盒中的错误信息传递给服务器 // 设置异常捕捉的回调函数 NSSetUncaughtExceptionHandler(handleException); return YES; }
- 优秀三方奔溃统计平台
友盟
(国内的)Crashlytics
(国外的,比较牛逼)Flurry
(国外的,统计)
利用RunLoop奔溃而不死,
仅供学习,不要这么做
,这种用户体验不好- (void)handle { UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:@"哎呀" message:@"让你乱点,傻逼了吧!" delegate:self cancelButtonTitle:@"好的" otherButtonTitles:nil, nil]; [alertView show]; // 重新启动RunLoop [[NSRunLoop currentRunLoop] addPort:[NSPort port] forMode:NSDefaultRunLoopMode]; [[NSRunLoop currentRunLoop] run]; } - (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex { NSLog(@"---点击好的---"); // 退出程序 exit(0); } void handleException(NSException *exception) { // 因为这是C语言函数,所以【不能】直接用[self performSelector:@selector(handle)]调用 [[UIApplication sharedApplication].delegate performSelector:@selector(handle)]; } - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { // 设置捕捉异常的回调 NSSetUncaughtExceptionHandler(handleException); return YES; }