[iOS]异常捕捉
程序员文章站
2022-06-30 19:32:27
UncaughtExceptionHandler.h UncaughtExceptionHandler.m 开启异常捕捉 异常示例 运行效果 ......
uncaughtexceptionhandler.h
#import <foundation/foundation.h> ns_assume_nonnull_begin @interface uncaughtexceptionhandler : nsobject @end void uncaughtexceptionhandlerstart(void); ns_assume_nonnull_end
uncaughtexceptionhandler.m
#import "uncaughtexceptionhandler.h" #import <uikit/uikit.h> #import <libkern/osatomic.h> #import <execinfo.h> 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; @interface uncaughtexceptionhandler () { bool dismissed; } @end @implementation uncaughtexceptionhandler + (nsarray *)backtrace { void *callstack[128]; int frames = backtrace(callstack, 128); char **strs = backtrace_symbols(callstack, frames); nsmutablearray *backtrace = [nsmutablearray arraywithcapacity:frames]; int end = uncaughtexceptionhandlerskipaddresscount + uncaughtexceptionhandlerreportaddresscount; for (int i = uncaughtexceptionhandlerskipaddresscount;i < end;i++) { [backtrace addobject:[nsstring stringwithutf8string:strs[i]]]; } free(strs); return backtrace; } - (void)handleexception:(nsexception *)exception { nsstring *reason = [exception reason]; nsstring *addresses = [[exception userinfo] objectforkey:uncaughtexceptionhandleraddresseskey]; uialertview *alert = [[uialertview alloc] initwithtitle:@"" message:[nsstring stringwithformat:@"reason:%@\n addresses:%@",reason,addresses] delegate:self cancelbuttontitle:@"退出" otherbuttontitles:@"继续", nil]; [alert show]; cfrunloopref runloop = cfrunloopgetcurrent(); cfarrayref allmodes = cfrunloopcopyallmodes(runloop); while (!dismissed) { for (nsstring *mode in (__bridge 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); if ([[exception name] isequal:uncaughtexceptionhandlersignalexceptionname]) { kill(getpid(), [[[exception userinfo] objectforkey:uncaughtexceptionhandlersignalkey] intvalue]); }else{ [exception raise]; } } - (void)alertview:(uialertview *)analertview clickedbuttonatindex:(nsinteger)anindex { if (anindex == 0) { dismissed = yes; } } @end void handleexception(nsexception *exception); void signalhandler(int signal); void uncaughtexceptionhandlerstart(void) { nssetuncaughtexceptionhandler(&handleexception); signal(sigabrt, signalhandler); signal(sigill, signalhandler); signal(sigsegv, signalhandler); signal(sigfpe, signalhandler); signal(sigbus, signalhandler); signal(sigpipe, signalhandler); } void handleexception(nsexception *exception) { int32_t exceptioncount = osatomicincrement32(&uncaughtexceptioncount); if (exceptioncount > uncaughtexceptionmaximum) { return; } nsarray *callstack = [uncaughtexceptionhandler backtrace]; nsmutabledictionary *userinfo = [nsmutabledictionary dictionarywithdictionary:[exception userinfo]]; [userinfo setobject:callstack forkey:uncaughtexceptionhandleraddresseskey]; [[[uncaughtexceptionhandler alloc] init] performselectoronmainthread:@selector(handleexception:) withobject:[nsexception exceptionwithname:[exception name] reason:[exception reason] userinfo:userinfo] waituntildone:yes]; } void signalhandler(int signal) { 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] performselectoronmainthread:@selector(handleexception:) withobject:[nsexception exceptionwithname:uncaughtexceptionhandlersignalexceptionname reason:[nsstring stringwithformat:@"signal %d was raised.",signal] userinfo:[nsdictionary dictionarywithobject:[nsnumber numberwithint:signal] forkey:uncaughtexceptionhandlersignalkey]] waituntildone:yes]; }
开启异常捕捉
#import "appdelegate.h" #import "uncaughtexceptionhandler.h" @interface appdelegate () @end @implementation appdelegate - (bool)application:(uiapplication *)application didfinishlaunchingwithoptions:(nsdictionary *)launchoptions { // override point for customization after application launch. uncaughtexceptionhandlerstart(); return yes; }
异常示例
- (void)touchesbegan:(nsset<uitouch *> *)touches withevent:(uievent *)event { nsarray *array = @[@"1"]; nslog(@"%@",array[5]); }
运行效果