IOS app crashes are always a vexing problem, but crashing without knowing the cause of the bug is even more vexing.
Fortunately, Apple’s own crash detection API and Runloop can resurrect the application once, but it will crash the second time, but it is still a useful tip.
Here are the classes that IOS crashes resurrect and how to use them
#import "crashhandler. h" // report crash records in Appdelagte - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { // Override point for customization after application launch. [CrashHandler sharedInstance]; return YES; } //.h file #import <Foundation/ foundation. h> @interface CrashHandler: NSObject {BOOL ignore; } + (instancetype)sharedInstance; #import "CrashHandler. H "#import <UIKit/ uikit. h> #include <libkern/OSAtomic. H > #include <execinfo.h> NSString * const kSignalExceptionName = @"kSignalExceptionName"; NSString * const kSignalKey = @"kSignalKey"; NSString * const kCaughtExceptionStackInfoKey = @"kCaughtExceptionStackInfoKey"; void HandleException(NSException *exception); void SignalHandler(int signal); @implementation CrashHandler static CrashHandler *instance = nil; + (instancetype)sharedInstance { static dispatch_once_t onceToken; dispatch_once(&onceToken, ^{ instance = [[[self class] alloc] init]; }); return instance; } + (instancetype)allocWithZone:(struct _NSZone *)zone { static dispatch_once_t onceToken; dispatch_once(&onceToken, ^{ instance = [super allocWithZone:zone]; }); return instance; } - (instancetype)init { self = [super init]; if (self) { [self setCatchExceptionHandler]; } return self; } - (void)setCatchExceptionHandler { // 1. Capture some defect in the collapse of the NSSetUncaughtExceptionHandler (& HandleException); Signal (SIGABRT, SignalHandler); signal(SIGILL, SignalHandler); signal(SIGSEGV, SignalHandler); signal(SIGFPE, SignalHandler); signal(SIGBUS, SignalHandler); signal(SIGPIPE, SignalHandler); } + (NSArray *)backtrace { void* callstack[128]; int frames = backtrace(callstack, 128); char **strs = backtrace_symbols(callstack, frames); NSMutableArray *backtrace = [NSMutableArray arrayWithCapacity:frames]; for (int i = 0; i < frames; i++) { [backtrace addObject:[NSString stringWithUTF8String:strs[i]]]; } free(strs); return backtrace; } - (void)alertView:(UIAlertView *)anAlertView clickedButtonAtIndex:(NSInteger)anIndex { if (anIndex == 0) { ignore = YES; } else if (anIndex == 1) {NSLog(@" undead "); } } - (void)handleException:(NSException *)exception { NSString *message = [NSString StringWithFormat :@" Crash cause :\n%@\n%@", [exception reason], [[exception userInfo] objectForKey:kCaughtExceptionStackInfoKey]]; NSLog(@"%@",message); UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@" The program crashed "message:@" If you can bring the program back to life, What's your decision? "Delegate :self cancelButtonTitle:@" otherButtonTitles:@" Nil"; [alert show]; CFRunLoopRef runLoop = CFRunLoopGetCurrent(); CFArrayRef allModes = CFRunLoopCopyAllModes(runLoop); while (! Ignore) {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:kSignalExceptionName]) { kill(getpid(), [[[exception userInfo] objectForKey:kSignalKey] intValue]); } else { [exception raise]; }} @end void HandleException(NSException *exception) {NSArray *callStack = [exception callStackSymbols]; NSMutableDictionary *userInfo = [NSMutableDictionary dictionary]; [userInfo setObject:callStack forKey:kCaughtExceptionStackInfoKey]; CrashHandler *crashObject = [CrashHandler sharedInstance]; NSException *customException = [NSException exceptionWithName:[exception name] reason:[exception reason] userInfo:userInfo]; [crashObject performSelectorOnMainThread: @selector(handleException:) withObject:customException waitUntilDone:YES]; } void SignalHandler(int signal) {NSArray *callStack = [CrashHandler backtrace]; NSLog(@" signal capture crash, stack info: %@",callStack); CrashHandler *crashObject = [CrashHandler sharedInstance]; NSException *customException = [NSException exceptionWithName:kSignalExceptionName reason:[NSString stringWithFormat:NSLocalizedString(@"Signal %d was raised.", nil),signal] userInfo:@{kSignalKey:[NSNumber numberWithInt:signal]}]; [crashObject performSelectorOnMainThread: @selector(handleException:) withObject:customException waitUntilDone:YES]; }Copy the code