IOS 捕获程序异常

iOS开发中我们会遇到程序抛出异常退出的情况,如果是在调试的过程中,异常的信息是一目了然,但是如果是在已经发布的程序中,获取异常的信息有时候是比较困难的。

 iOS提供了异常发生的处理API,我们在程序启动的时候可以添加这样的Handler,这样的程序发生异常的时候就可以对这一部分的信息进行必要的处理,适时的反馈给开发者。

首先定义一个类SignalHandler

 @interface SignalHandler : NSObject

 + (instancetype)Instance;

- (void)setExceptionHandler;

 @end

 

实现SignalHandler.m

#import "SignalHandler.h"

#import <UIKit/UIKit.h>

#include <libkern/OSAtomic.h>

#include <execinfo.h>

 @interface SignalHandler ()

{

    BOOL isDismissed ;

}

- (void)HandleException1:(NSException *)exception;

 

@end

 

//捕获信号后的回调函数

void HandleException(NSException *exception)

{

    //处理异常消息

    [[SignalHandler Instance] performSelectorOnMainThread:@selector(HandleException1:) withObject:exception waitUntilDone:YES];

}

 

@implementation SignalHandler

 

static  SignalHandler *s_SignalHandler =  nil;

 

+ (instancetype)Instance{

       static dispatch_once_t onceToken;

    dispatch_once(&onceToken, ^{

        if (s_SignalHandler == nil) {

            s_SignalHandler  =  [[SignalHandler alloc] init];

        }

    });

        return s_SignalHandler;

}

 

- (void)setExceptionHandler

{

    NSSetUncaughtExceptionHandler(&HandleException);

}

 

 

//处理异常用到的方法

- (void)HandleException1:(NSException *)exception

{

    CFRunLoopRef runLoop = CFRunLoopGetCurrent();

    CFArrayRef allModes = CFRunLoopCopyAllModes(runLoop);

    //异常的堆栈信息

    NSArray *stackArray = [exception callStackSymbols];

    //出现异常的原因

    NSString *reason = [exception reason];

    // 异常名称

    NSString *name = [exception name];

    NSString *exceptionInfo = [NSString stringWithFormat:@"原因:%@ 名称:%@ 堆栈:%@",name, reason, stackArray];

    NSLog(@"%@", exceptionInfo);

    

    

    //此处也可以把exceptionInfo保存文件

    UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:@"程序出现问题啦" message:exceptionInfo delegate:self cancelButtonTitle:@"Cancel" otherButtonTitles:nil];

    [alertView show];

    

    //当接收到异常处理消息时,让程序开始runloop,防止程序死亡

    while (!isDismissed) {

        for (NSString *mode in (__bridge NSArray *)allModes)

        {

            CFRunLoopRunInMode((CFStringRef)mode, 0.001, false);

        }

    }

     //当点击弹出视图的Cancel按钮哦,isDimissed YES,上边的循环跳出

    CFRelease(allModes);

    NSSetUncaughtExceptionHandler(NULL);

}

 

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

{

    //因为这个弹出视图只有一个Cancel按钮,所以直接进行修改isDimsmissed这个变量了

    isDismissed = YES;

}

最后需要在

didFinishLaunchingWithOptions中添加

  [[SignalHandler Instance] setExceptionHandler];

完成后就可以进行验证了,加入以下代码

  NSArray *array = [NSArray arrayWithObjects:@"1", nil];

    [array objectAtIndex:2];

如图

 

 

原文地址:https://www.cnblogs.com/menchao/p/4863485.html