IOS应用崩溃复活
2021/9/8 13:06:20
本文主要是介绍IOS应用崩溃复活,对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!
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 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.捕获一些异常导致的崩溃 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: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(@"信号捕获崩溃,堆栈信息:%@",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]; }
这篇关于IOS应用崩溃复活的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!
- 2024-11-12Axios库资料:新手入门必读教程
- 2024-11-11Axios库项目实战:新手入门教程
- 2024-09-29Axios库教程:初学者必备指南
- 2024-08-29Axios库资料:新手入门指南与基本使用教程
- 2024-03-14system bios shadowed
- 2024-03-14gabios
- 2024-02-07iOS应用提交上架的最新流程
- 2024-02-06打包 iOS 的 IPA 文件
- 2023-12-07uniapp打包iOS应用并通过审核:代码混淆的终极解决方案 ?
- 2023-11-25uniapp IOS从打包到上架流程(详细简单) 原创