美文网首页OC-开发案例收集很常关于app安全性
iOS开发知识体系之《 Crash闪退日志的捕获》

iOS开发知识体系之《 Crash闪退日志的捕获》

作者: 小呆一哥 | 来源:发表于2021-03-30 09:49 被阅读0次

    如何捕获app闪退的原因?如何将闪退的原因发送到服务器?

    一、异常处理:预先设置捕获的异常和未知异常。

    预先设置捕获的异常的处理
    该种异常是通过标准的@try @catch(id exception) @finally 来处理的。

    @try {
    // 有可能出现异常的代码块,可以创建异常对象并且手动抛出异常或者在执行可能出现的代码会自动触发并抛出异常
    
    } @catch (id exception)  // 大部分情况下是通过直接指定异常参数@catch(NSException *e)
    {
    // 捕获到异常的处理措施
    
    } @finally {
    // 无论有无异常都要执行的操作,例如某些资源的释放等。
    
    }
    

    对于@try代码块中出现的异常,会将异常发送到@catch代码块中进行处理。在这种情况下出现的异常情况,不会将异常发送到系统级别,因此不会引起系统的闪退情况。

    接下来写代码测试


    image.png

    捕捉闪退信息如下:


    image.png

    预先设置对异常的捕获,不会引起app的闪退。没有对可能发生异常的地方进行处理机制,会引起app的闪退。

    二、未知异常的捕获
    在默认情况下,系统发生了未知异常,系统会捕获该异常并且退出app。发生异常后,系统会创建一个NSExcetion对象,并且在异常出抛出,等待有接受者,若没有传递给系统处理。那么如何来获取这个未知异常呢?该问题问的好!利用如下函数来解决这个问题:

    FOUNDATION_EXPORT void NSSetUncaughtExceptionHandler(NSUncaughtExceptionHandler * _Nullable);

    该函数是一个全局的函数,该函数一般在app开始的时候调用,该函数的意义:设置未知异常的捕获函数,参数是未知异常处理函数的函数名,该未知异常处理函数的模式如下:
    typedef void NSUncaughtExceptionHandler(NSException *exception);

    未知异常处理函数的示例

    void uncaughtExceptionHandler(NSException *exception) {
        
       // 在app退出前的一些处理任务,系统会等待该函数的执行完毕
        NSLog(@"CRASH: %@", exception);
        NSLog(@"Stack Trace: %@", [exception callStackSymbols]);
        NSLog(@"处理crashing ~~~~~~~~~~ !");
        sleep(10);
        NSLog(@"处理crashing end~~~~~~~~~~ !");
    }
    
    - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
      
        NSSetUncaughtExceptionHandler(&uncaughtExceptionHandler);
        return YES;
    }
    

    备注:在app退出前的一些处理任务,系统会等待该函数的执行完毕,上面代码中我们进行了线程 sleep(10)来进行测试,收到异常后程序是否立即退出,也就是收到异常后能否立即将闪退日志信息上传到服务端。

    接下来代码测试结果如下:

    2021-03-29 15:45:42.915127+0800 PodLoad[61855:2325664] CRASH: *** -[__NSArrayM insertObject:atIndex:]: object cannot be nil
    2021-03-29 15:45:42.915467+0800 PodLoad[61855:2325664] Stack Trace: (
        0   CoreFoundation                      0x00007fff20421af6 __exceptionPreprocess + 242
        1   libobjc.A.dylib                     0x00007fff20177e78 objc_exception_throw + 48
        2   CoreFoundation                      0x00007fff2049e77f _CFThrowFormattedException + 194
        3   CoreFoundation                      0x00007fff2049c656 -[__NSArrayM insertObject:atIndex:].cold.2 + 0
        4   CoreFoundation                      0x00007fff2031f678 -[__NSArrayM insertObject:atIndex:] + 1134
        5   PodLoad                             0x0000000103918c23 -[ViewController touchesBegan:withEvent:] + 115
        6   UIKitCore                           0x00007fff246ca70f forwardTouchMethod + 321
        7   UIKitCore                           0x00007fff246ca5bd -[UIResponder touchesBegan:withEvent:] + 49
        8   UIKitCore                           0x00007fff246d95b5 -[UIWindow _sendTouchesForEvent:] + 622
        9   UIKitCore                           0x00007fff246db6c7 -[UIWindow sendEvent:] + 4774
        10  UIKitCore                           0x00007fff246b5466 -[UIApplication sendEvent:] + 633
        11  UIKitCore                           0x00007fff24745f04 __processEventQueue + 13895
        12  UIKitCore                           0x00007fff2473c877 __eventFetcherSourceCallback + 104
        13  CoreFoundation                      0x00007fff2039038a __CFRUNLOOP_IS_CALLING_OUT_TO_A_SOURCE0_PERFORM_FUNCTION__ + 17
        14  CoreFoundation                      0x00007fff20390282 __CFRunLoopDoSource0 + 180
        15  CoreFoundation                      0x00007fff2038f764 __CFRunLoopDoSources0 + 248
        16  CoreFoundation                      0x00007fff20389f2f __CFRunLoopRun + 878
        17  CoreFoundation                      0x00007fff203896d6 CFRunLoopRunSpecific + 567
        18  GraphicsServices                    0x00007fff2c257db3 GSEventRunModal + 139
        19  UIKitCore                           0x00007fff24696cf7 -[UIApplication _run] + 912
        20  UIKitCore                           0x00007fff2469bba8 UIApplicationMain + 101
        21  PodLoad                             0x0000000103918fb2 main + 114
        22  libdyld.dylib                       0x00007fff2025a3e9 start + 1
        23  ???                                 0x0000000000000001 0x0 + 1
    )
    2021-03-29 15:45:42.917124+0800 PodLoad[61855:2325664] 处理crashing ~~~~~~~~~~ !
    2021-03-29 15:45:52.918737+0800 PodLoad[61855:2325664] 处理crashing end~~~~~~~~~~ !
    2021-03-29 15:45:52.919067+0800 PodLoad[61855:2325664] *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '*** -[__NSArrayM insertObject:atIndex:]: object cannot be nil'
    *** First throw call stack:
    (
        0   CoreFoundation                      0x00007fff20421af6 __exceptionPreprocess + 242
        1   libobjc.A.dylib                     0x00007fff20177e78 objc_exception_throw + 48
        2   CoreFoundation                      0x00007fff2049e77f _CFThrowFormattedException + 194
        3   CoreFoundation                      0x00007fff2049c656 -[__NSArrayM insertObject:atIndex:].cold.2 + 0
        4   CoreFoundation                      0x00007fff2031f678 -[__NSArrayM insertObject:atIndex:] + 1134
        5   PodLoad                             0x0000000103918c23 -[ViewController touchesBegan:withEvent:] + 115
        6   UIKitCore                           0x00007fff246ca70f forwardTouchMethod + 321
        7   UIKitCore                           0x00007fff246ca5bd -[UIResponder touchesBegan:withEvent:] + 49
        8   UIKitCore                           0x00007fff246d95b5 -[UIWindow _sendTouchesForEvent:] + 622
        9   UIKitCore                           0x00007fff246db6c7 -[UIWindow sendEvent:] + 4774
        10  UIKitCore                           0x00007fff246b5466 -[UIApplication sendEvent:] + 633
        11  UIKitCore                           0x00007fff24745f04 __processEventQueue + 13895
        12  UIKitCore                           0x00007fff2473c877 __eventFetcherSourceCallback + 104
        13  CoreFoundation                      0x00007fff2039038a __CFRUNLOOP_IS_CALLING_OUT_TO_A_SOURCE0_PERFORM_FUNCTION__ + 17
        14  CoreFoundation                      0x00007fff20390282 __CFRunLoopDoSource0 + 180
        15  CoreFoundation                      0x00007fff2038f764 __CFRunLoopDoSources0 + 248
        16  CoreFoundation                      0x00007fff20389f2f __CFRunLoopRun + 878
        17  CoreFoundation                      0x00007fff203896d6 CFRunLoopRunSpecific + 567
        18  GraphicsServices                    0x00007fff2c257db3 GSEventRunModal + 139
        19  UIKitCore                           0x00007fff24696cf7 -[UIApplication _run] + 912
        20  UIKitCore                           0x00007fff2469bba8 UIApplicationMain + 101
        21  PodLoad                             0x0000000103918fb2 main + 114
        22  libdyld.dylib                       0x00007fff2025a3e9 start + 1
        23  ???                                 0x0000000000000001 0x0 + 1
    )
    libc++abi.dylib: terminating with uncaught exception of type NSException
    *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '*** -[__NSArrayM insertObject:atIndex:]: object cannot be nil'
    terminating with uncaught exception of type NSException
    

    可见sleep(10)结束之后才结束APP

    日志信息上传
    关键是需要进行同步操作,使得闪退日志上传成功后再结束APP进程。

    比较成熟的第三方闪退监控平台:Bugly、友盟等

    相关文章

      网友评论

        本文标题:iOS开发知识体系之《 Crash闪退日志的捕获》

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