美文网首页
iOS 崩溃异常捕获

iOS 崩溃异常捕获

作者: 黑暗森林的歌者 | 来源:发表于2016-07-21 15:37 被阅读309次

    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);
    }
    

    相关文章

      网友评论

          本文标题:iOS 崩溃异常捕获

          本文链接:https://www.haomeiwen.com/subject/nhpbjttx.html