iOS已经提供了捕获异常的机制
NSSetUncaughtExceptionHandler
我们就创建一个捕获crash的类,其中写好分析崩溃原因的方法
头文件
#import@interface UncaughtExceptionHandler : NSObject{}@endvoid HandleException(NSException *exception);void SignalHandler(int signal);//在didFinishLaunchingWithOptions中添加这个方法//添加一行 /* InstallUncaughtExceptionHandler();*/void InstallUncaughtExceptionHandler(void);复制代码
.m文件
定义
#include#include NSString * const UncaughtExceptionHandlerSignalExceptionName = @"UncaughtExceptionHandlerSignalExceptionName";NSString * const UncaughtExceptionHandlerSignalKey = @"UncaughtExceptionHandlerSignalKey";NSString * const UncaughtExceptionHandlerAddressesKey = @"UncaughtExceptionHandlerAddressesKey";volatile int32_t UncaughtExceptionCount = 0;const int32_t UncaughtExceptionMaximum = 10;const NSInteger UncaughtExceptionHandlerSkipAddressCount = 4;const NSInteger UncaughtExceptionHandlerReportAddressCount = 5;复制代码
实现方法
@implementation UncaughtExceptionHandler+ (NSArray *)backtrace{ void* callstack[128]; int frames = backtrace(callstack, 128); char **strs = backtrace_symbols(callstack, frames); int i; NSMutableArray *backtrace = [NSMutableArray arrayWithCapacity:frames]; for ( i = UncaughtExceptionHandlerSkipAddressCount; i < UncaughtExceptionHandlerSkipAddressCount + UncaughtExceptionHandlerReportAddressCount; i++) { [backtrace addObject:[NSString stringWithUTF8String:strs[i]]]; } free(strs); return backtrace;}- (void)handleException:(NSException *)exception{ //可以在这个方法中打印或者弹出alert显示出来错误信息/*弹窗的message可以是 [NSString stringWithFormat:NSLocalizedString( @"你可以执行一些崩溃后需要做的事情.\n" @"%@\n%@", nil), [exception reason], //崩溃内容 [[exception userInfo] objectForKey:UncaughtExceptionHandlerAddressesKey]]*/ CFRunLoopRef runLoop = CFRunLoopGetCurrent(); CFArrayRef allModes = CFRunLoopCopyAllModes(runLoop); while (!dismissed) { for (NSString *mode in (NSArray *)allModes) { CFRunLoopRunInMode((CFStringRef)mode, 0.001, false); } } CFRelease(allModes); NSSetUncaughtExceptionHandler(NULL); signal(SIGABRT, SIG_DFL); signal(SIGILL, SIG_DFL); signal(SIGSEGV, SIG_DFL); signal(SIGFPE, SIG_DFL); signal(SIGBUS, SIG_DFL); signal(SIGPIPE, SIG_DFL); { kill(getpid(),[[[[exception userInfo] allValues] lastObject] intValue]); }}@end复制代码
void HandleException(NSException *exception){ int32_t exceptionCount = OSAtomicIncrement32(&UncaughtExceptionCount); if (exceptionCount > UncaughtExceptionMaximum) { return; } NSArray *callStack = [exception callStackSymbols];//堆栈调用信息 //[UncaughtExceptionHandler backtrace]; NSMutableDictionary *userInfo = [NSMutableDictionary dictionaryWithDictionary:[exception userInfo]]; [userInfo setObject:callStack forKey:UncaughtExceptionHandlerAddressesKey]; [[[[UncaughtExceptionHandler alloc] init] autorelease] performSelectorOnMainThread:@selector(handleException:) withObject: [NSException exceptionWithName:[exception name] reason:[exception reason] userInfo:userInfo] waitUntilDone:YES];}void SignalHandler(int signal){ NSLog(@"handleException 4"); int32_t exceptionCount = OSAtomicIncrement32(&UncaughtExceptionCount); if (exceptionCount > UncaughtExceptionMaximum) { return; } NSMutableDictionary *userInfo = [NSMutableDictionary dictionaryWithObject:[NSNumber numberWithInt:signal] forKey:UncaughtExceptionHandlerSignalKey]; NSArray *callStack = [UncaughtExceptionHandler backtrace]; [userInfo setObject:callStack forKey:UncaughtExceptionHandlerAddressesKey]; [[[[UncaughtExceptionHandler alloc] init] autorelease] performSelectorOnMainThread:@selector(handleException:) withObject: [NSException exceptionWithName:UncaughtExceptionHandlerSignalExceptionName reason: [NSString stringWithFormat: NSLocalizedString(@"Signal %d was raised.", nil), signal] userInfo: [NSDictionary dictionaryWithObject:[NSNumber numberWithInt:signal] forKey:UncaughtExceptionHandlerSignalKey]] waitUntilDone:YES];}void InstallUncaughtExceptionHandler(void){ NSSetUncaughtExceptionHandler(&HandleException); signal(SIGABRT, SignalHandler); signal(SIGILL, SignalHandler); signal(SIGSEGV, SignalHandler); signal(SIGFPE, SignalHandler); signal(SIGBUS, SignalHandler); signal(SIGPIPE, SignalHandler);}复制代码