当前位置: 移动技术网 > IT编程>移动开发>IOS > [iOS]异常捕捉

[iOS]异常捕捉

2018年11月20日  | 移动技术网IT编程  | 我要评论

少林老女,risk.bho,佣兵天下后传

uncaughtexceptionhandler.h

#import <foundation/foundation.h>

ns_assume_nonnull_begin

@interface uncaughtexceptionhandler : nsobject

@end

void uncaughtexceptionhandlerstart(void);

ns_assume_nonnull_end

uncaughtexceptionhandler.m

#import "uncaughtexceptionhandler.h"
#import <uikit/uikit.h>
#import <libkern/osatomic.h>
#import <execinfo.h>

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;

@interface uncaughtexceptionhandler ()
{
    bool dismissed;
}
@end

@implementation uncaughtexceptionhandler

+ (nsarray *)backtrace
{
    void *callstack[128];
    int frames = backtrace(callstack, 128);
    char **strs = backtrace_symbols(callstack, frames);
    
    nsmutablearray *backtrace = [nsmutablearray arraywithcapacity:frames];
    int end = uncaughtexceptionhandlerskipaddresscount + uncaughtexceptionhandlerreportaddresscount;
    
    for (int i = uncaughtexceptionhandlerskipaddresscount;i < end;i++)
    {
        [backtrace addobject:[nsstring stringwithutf8string:strs[i]]];
    }
    free(strs);
    
    return backtrace;
}

- (void)handleexception:(nsexception *)exception
{
    nsstring *reason = [exception reason];
    nsstring *addresses = [[exception userinfo] objectforkey:uncaughtexceptionhandleraddresseskey];
    uialertview *alert = [[uialertview alloc] initwithtitle:@""
                                                    message:[nsstring stringwithformat:@"reason:%@\n addresses:%@",reason,addresses]
                                                   delegate:self
                                          cancelbuttontitle:@"退出"
                                          otherbuttontitles:@"继续", nil];
    [alert show];
    
    cfrunloopref runloop = cfrunloopgetcurrent();
    cfarrayref allmodes = cfrunloopcopyallmodes(runloop);
    
    while (!dismissed)
    {
        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:uncaughtexceptionhandlersignalexceptionname])
    {
        kill(getpid(), [[[exception userinfo] objectforkey:uncaughtexceptionhandlersignalkey] intvalue]);
    }else{
        [exception raise];
    }
}

- (void)alertview:(uialertview *)analertview clickedbuttonatindex:(nsinteger)anindex
{
    if (anindex == 0)
    {
        dismissed = yes;
    }
}

@end

void handleexception(nsexception *exception);
void signalhandler(int signal);

void uncaughtexceptionhandlerstart(void)
{
    nssetuncaughtexceptionhandler(&handleexception);
    signal(sigabrt, signalhandler);
    signal(sigill, signalhandler);
    signal(sigsegv, signalhandler);
    signal(sigfpe, signalhandler);
    signal(sigbus, signalhandler);
    signal(sigpipe, signalhandler);
}

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] 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] performselectoronmainthread:@selector(handleexception:)
                                                              withobject:[nsexception exceptionwithname:uncaughtexceptionhandlersignalexceptionname
                                                                                                 reason:[nsstring stringwithformat:@"signal %d was raised.",signal]
                                                                                               userinfo:[nsdictionary dictionarywithobject:[nsnumber numberwithint:signal]
                                                                                                                                    forkey:uncaughtexceptionhandlersignalkey]]
                                                           waituntildone:yes];
}

开启异常捕捉

#import "appdelegate.h"
#import "uncaughtexceptionhandler.h"

@interface appdelegate ()

@end

@implementation appdelegate

- (bool)application:(uiapplication *)application didfinishlaunchingwithoptions:(nsdictionary *)launchoptions
{
    // override point for customization after application launch.
    
    uncaughtexceptionhandlerstart();
    
    return yes;
}

异常示例

- (void)touchesbegan:(nsset<uitouch *> *)touches withevent:(uievent *)event
{
    nsarray *array = @[@"1"];
    nslog(@"%@",array[5]);
}

运行效果

 

如对本文有疑问,请在下面进行留言讨论,广大热心网友会与你互动!! 点击进行留言回复

相关文章:

验证码:
移动技术网