iOS 崩溃异常捕获

iOS已经提供了捕获异常的机制

NSSetUncaughtExceptionHandler

我们就创建一个捕获crash的类,其中写好分析崩溃原因的方法

头文件

#import <UIKit/UIKit.h>

@interface UncaughtExceptionHandler : NSObject{

}

@end

void HandleException(NSException *exception);
void SignalHandler(int signal);

//在didFinishLaunchingWithOptions中添加这个方法
//添加一行  
/*
  InstallUncaughtExceptionHandler();
*/
void InstallUncaughtExceptionHandler(void);
复制代码

.m文件

定义

#include <libkern/OSAtomic.h>
#include <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;
复制代码

实现方法

@implementation UncaughtExceptionHandler

+ (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)handleException:(NSException *)exception
{
 //可以在这个方法中打印或者弹出alert显示出来错误信息
/*弹窗的message可以是
  [NSString stringWithFormat:NSLocalizedString(   
                @"你可以执行一些崩溃后需要做的事情.\n"  
                @"%@\n%@", nil),  
                [exception reason],    //崩溃内容 
                [[exception userInfo] objectForKey:UncaughtExceptionHandlerAddressesKey]]
*/
 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);
 
    {
        kill(getpid(),[[[[exception userInfo] allValues] lastObject] intValue]);
    }

}

@end
复制代码
void HandleException(NSException *exception)
{
 int32_t exceptionCount = OSAtomicIncrement32(&UncaughtExceptionCount);
 if (exceptionCount > UncaughtExceptionMaximum)
 {
  return;
 }
 
 NSArray *callStack = [exception callStackSymbols];//堆栈调用信息
    //[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)
{
      NSLog(@"handleException 4");
 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);
}
复制代码

转载于:https://juejin.im/post/5a93c9385188257a7b5aba42

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值