1. 程式人生 > >iOS 崩潰資訊攔截防止閃退

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(

void);

//_______________________.m________________________________________

#import "UncaughtExceptionHandler.h"

#include <libkern/OSAtomic.h>

#include <execinfo.h>

NSString *const UncaughtExceptionHandlerSignalExceptionName =@"UncaughtExceptionHandlerSignalExceptionName";

NSString

*const UncaughtExceptionHandlerSignalKey =@"UncaughtExceptionHandlerSignalKey";

NSString *const UncaughtExceptionHandlerAddressesKey =@"UncaughtExceptionHandlerAddressesKey";

volatileint32_t UncaughtExceptionCount =0;

constint32_t UncaughtExceptionMaximum =10;

constNSInteger UncaughtExceptionHandlerSkipAddressCount =

4;

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;

}