IOS异常捕捉

.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>

@implementation UncaughtExceptionHandler

//http://www.cocoachina.com/newbie/tutorial/2012/0829/4672.html

NSString * const UncaughtExceptionHandlerSignalExceptionName = @"UncaughtExceptionHandlerSignalExceptionName";

NSString * const UncaughtExceptionHandlerSignalKey = @"UncaughtExceptionHandlerSignalKey";

NSString * const UncaughtExceptionHandlerAddressesKey = @"UncaughtExceptionHandlerAddressesKey";

volatile int32_t UncaughtExceptionCount = 0;

const int32_t UncaughtExceptionMaximum = 10;

const NSInteger UncaughtExceptionHandlerSkipAddressCount = 4;

const NSInteger UncaughtExceptionHandlerReportAddressCount = 5;

+ (NSArray *)backtrace

{

    void* callstack[128];

    int frames = backtrace(callstack, 128);

    char **strs = backtrace_symbols(callstack, frames);

       int i;

    NSMutableArray *backtrace = [NSMutableArray arrayWithCapacity:frames];

    for (

         i = UncaughtExceptionHandlerSkipAddressCount;

         i < UncaughtExceptionHandlerSkipAddressCount +

         UncaughtExceptionHandlerReportAddressCount;

         i++)

    {

        [backtrace addObject:[NSString stringWithUTF8String:strs[i]]];

    }

    free(strs);

       return backtrace;

}


- (void)alertView:(UIAlertView *)anAlertView clickedButtonAtIndex:(NSInteger)anIndex

{

    if (anIndex == 0)

    {

        dismissed = YES;

    }else if (anIndex==1) {

        NSLog(@"ssssssss");

    }

}


- (void)validateAndSaveCriticalApplicationData

{

    

}


- (void)handleException:(NSException *)exception

{

    [self validateAndSaveCriticalApplicationData];

    NSString *message = [NSString stringWithFormat:NSLocalizedString(@"异常原因如下:\n%@\n%@", nil),

                         [exception reason],

                         [[exception userInfo] objectForKey:UncaughtExceptionHandlerAddressesKey]];

    NSLog(@"%@",message);

    

    UIAlertView *alert =

    [[[UIAlertView alloc]

      initWithTitle:NSLocalizedString(@"抱歉,程序出现了异常", nil)

      message:[NSString stringWithFormat:NSLocalizedString(

                                                           @"如果点击继续,程序有可能会出现其他的问题,建议您还是点击退出按钮并重新打开\n\n"

                                                           @"异常原因如下:\n%@\n%@", nil),

               [exception reason],

               [[exception userInfo] objectForKey:UncaughtExceptionHandlerAddressesKey]]

      delegate:self

      cancelButtonTitle:NSLocalizedString(@"退出", nil)

      otherButtonTitles:NSLocalizedString(@"继续", nil), nil]

     autorelease];

    [alert show];

    

    CFRunLoopRef runLoop = CFRunLoopGetCurrent();

    CFArrayRef allModes = CFRunLoopCopyAllModes(runLoop);

    

    while (!dismissed)

    {

        for (NSString *mode in (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:UncaughtExceptionHandlerSignalExceptionName])

    {

        kill(getpid(), [[[exception userInfo] objectForKey:UncaughtExceptionHandlerSignalKey] intValue]);

    }

    else

    {

        [exception raise];

    }

}


@end


void HandleException(NSException *exception)

{

    int32_t exceptionCount = OSAtomicIncrement32(&UncaughtExceptionCount);

    if (exceptionCount > UncaughtExceptionMaximum)

    {

        return;

    }

    

    NSArray *callStack = [UncaughtExceptionHandler backtrace];

    NSMutableDictionary *userInfo =

    [NSMutableDictionary dictionaryWithDictionary:[exception userInfo]];

    [userInfo

     setObject:callStack

     forKey:UncaughtExceptionHandlerAddressesKey];

    

    [[[[UncaughtExceptionHandler alloc] init] autorelease]

     performSelectorOnMainThread:@selector(handleException:)

     withObject:

     [NSException

      exceptionWithName:[exception name]

      reason:[exception reason]

      userInfo:userInfo]

     waitUntilDone:YES];

}


void SignalHandler(int signal)

{

    int32_t exceptionCount = OSAtomicIncrement32(&UncaughtExceptionCount);

    if (exceptionCount > UncaughtExceptionMaximum)

    {

        return;

    }

    

    NSMutableDictionary *userInfo =

    [NSMutableDictionary

     dictionaryWithObject:[NSNumber numberWithInt:signal]

     forKey:UncaughtExceptionHandlerSignalKey];

    

    NSArray *callStack = [UncaughtExceptionHandler backtrace];

    [userInfo

     setObject:callStack

     forKey:UncaughtExceptionHandlerAddressesKey];

    

    [[[[UncaughtExceptionHandler alloc] init] autorelease]

     performSelectorOnMainThread:@selector(handleException:)

     withObject:

     [NSException

      exceptionWithName:UncaughtExceptionHandlerSignalExceptionName

      reason:

      [NSString stringWithFormat:

       NSLocalizedString(@"Signal %d was raised.", nil),

       signal]

      userInfo:

      [NSDictionary

       dictionaryWithObject:[NSNumber numberWithInt: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();

.........

}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值