网站建设在整体布局有哪些要求/seo综合查询
IOS应用崩溃一直是一个很苦恼的问题,而崩溃的同时又未获取bug原因,更令人苦恼。
好在苹果自带的crash检测api,以及runloop可以让应用复活一次,不过第二次依旧会崩溃,但是还是一个很实用的小技巧。
以下是IOS崩溃复活的类和使用方法
#import "CrashHandler.h"//Appdelagte中注册crash记录上报- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {// Override point for customization after application launch.[CrashHandler sharedInstance];return YES;}//.h文件#import <Foundation/Foundation.h>@interface CrashHandler : NSObject{BOOL ignore;}+ (instancetype)sharedInstance;@end//.m文件#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 CrashHandlerstatic 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.捕获一些异常导致的崩溃NSSetUncaughtExceptionHandler(&HandleException);// 2.捕获非异常情况,通过signal传递出来的崩溃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(@"起死回生");}}- (void)handleException:(NSException *)exception{NSString *message = [NSString stringWithFormat:@"崩溃原因如下:\n%@\n%@",[exception reason],[[exception userInfo] objectForKey:kCaughtExceptionStackInfoKey]];NSLog(@"%@",message);UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"程序崩溃了"message:@"如果你能让程序起死回生,那你的决定是?"delegate:selfcancelButtonTitle:@"崩就蹦吧"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];}}@endvoid 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(@"信号捕获崩溃,堆栈信息:%@",callStack);CrashHandler *crashObject = [CrashHandler sharedInstance];NSException *customException = [NSException exceptionWithName:kSignalExceptionNamereason:[NSString stringWithFormat:NSLocalizedString(@"Signal %d was raised.", nil),signal]userInfo:@{kSignalKey:[NSNumber numberWithInt:signal]}];[crashObject performSelectorOnMainThread: @selector(handleException:) withObject:customException waitUntilDone:YES];}