iOS 崩潰資訊攔截防止閃退
//____________________.h_____________________________
#import<Foundation/Foundation.h>
#import <UIKit/UIKit.h>
@interface UncaughtExceptionHandler :NSObject{
BOOL dismissed;
}
@end
void HandleException(NSException *exception);
void SignalHandler(int signal);
void InstallUncaughtExceptionHandler(
//_______________________.m________________________________________
#import "UncaughtExceptionHandler.h"
#include <libkern/OSAtomic.h>
#include <execinfo.h>
NSString *const UncaughtExceptionHandlerSignalExceptionName =@"UncaughtExceptionHandlerSignalExceptionName";
NSString
NSString *const UncaughtExceptionHandlerAddressesKey =@"UncaughtExceptionHandlerAddressesKey";
volatileint32_t UncaughtExceptionCount =0;
constint32_t UncaughtExceptionMaximum =10;
constNSInteger UncaughtExceptionHandlerSkipAddressCount =
constNSInteger UncaughtExceptionHandlerReportAddressCount =5;
@implementation UncaughtExceptionHandler
+ (NSArray *)backtrace {
void* callstack[128];
int frames =backtrace(callstack, 128);
char **strs =backtrace_symbols(callstack, frames);
int i;
NSMutableArray *backtrace = [NSMutableArrayarrayWithCapacity:frames];
for (i = UncaughtExceptionHandlerSkipAddressCount ; i <UncaughtExceptionHandlerSkipAddressCount +UncaughtExceptionHandlerReportAddressCount; i++){
[backtraceaddObject:[NSStringstringWithUTF8String:strs[i]]];
}
free(strs);
return backtrace;
}
- (void)alertView:(UIAlertView *)anAlertView clickedButtonAtIndex:(NSInteger)anIndex {
if (anIndex ==0){
dismissed =YES;
}elseif (anIndex==1) {
NSLog(@"ssssssss");
}
}
- (void)validateAndSaveCriticalApplicationData {
}
- (void)handleException:(NSException *)exception {
[selfvalidateAndSaveCriticalApplicationData];
NSString *message = [NSStringstringWithFormat:NSLocalizedString(@"如果點選繼續,程式有可能會出現其他的問題,建議您還是點選退出按鈕並重新開啟\n\n"@"異常原因如下:\n%@\n%@",nil),[exceptionreason],[[exceptionuserInfo] objectForKey:UncaughtExceptionHandlerAddressesKey]];
UIAlertView *alert =[[UIAlertViewalloc]initWithTitle:NSLocalizedString(@"抱歉,程式出現了異常",nil)
message:message
delegate:self
cancelButtonTitle:NSLocalizedString(@"退出",nil)
otherButtonTitles:NSLocalizedString(@"繼續",nil), nil];
[alert show];
CFRunLoopRef runLoop = CFRunLoopGetCurrent();
CFArrayRef allModes = CFRunLoopCopyAllModes(runLoop);
while (!dismissed) {
for (NSString *modein (__bridgeNSArray *)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(), [[[exceptionuserInfo] objectForKey:UncaughtExceptionHandlerSignalKey]intValue]);
}else{
[exception raise];
}
}
@end
void HandleException(NSException *exception) {
int32_t exceptionCount =OSAtomicIncrement32(&UncaughtExceptionCount);
if (exceptionCount >UncaughtExceptionMaximum) {
return;
}
NSArray *callStack = [UncaughtExceptionHandlerbacktrace];
NSMutableDictionary *userInfo =[NSMutableDictionarydictionaryWithDictionary:[exceptionuserInfo]];[userInfo setObject:callStack forKey:UncaughtExceptionHandlerAddressesKey];
[[[UncaughtExceptionHandleralloc] init]performSelectorOnMainThread:@selector(handleException:)withObject:
[NSExceptionexceptionWithName:[exceptionname] reason:[exceptionreason] userInfo:userInfo]waitUntilDone:YES];
}
void SignalHandler(int signal) {
int32_t exceptionCount =OSAtomicIncrement32(&UncaughtExceptionCount);
if (exceptionCount >UncaughtExceptionMaximum) {
return;
}
NSMutableDictionary *userInfo =[NSMutableDictionarydictionaryWithObject:[NSNumbernumberWithInt:signal] forKey:UncaughtExceptionHandlerSignalKey];
NSArray *callStack = [UncaughtExceptionHandlerbacktrace];[userInfo setObject:callStackforKey:UncaughtExceptionHandlerAddressesKey];
[[[UncaughtExceptionHandleralloc] init]performSelectorOnMainThread:@selector(handleException:)withObject:[NSExceptionexceptionWithName:UncaughtExceptionHandlerSignalExceptionNamereason:[NSStringstringWithFormat:NSLocalizedString(@"Signal %d was raised.",nil),signal]userInfo:
[NSDictionarydictionaryWithObject:[NSNumbernumberWithInt: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);
}
//_________________呼叫_________________
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
InstallUncaughtExceptionHandler();
returnYES;
}