iOS開發(fā)知識體系之《 Crash閃退日志的捕獲》

如何捕獲app閃退的原因?如何將閃退的原因發(fā)送到服務器?

一、異常處理:預先設置捕獲的異常和未知異常。

預先設置捕獲的異常的處理
該種異常是通過標準的@try @catch(id exception) @finally 來處理的。

@try {
// 有可能出現(xiàn)異常的代碼塊,可以創(chuàng)建異常對象并且手動拋出異?;蛘咴趫?zhí)行可能出現(xiàn)的代碼會自動觸發(fā)并拋出異常

} @catch (id exception)  // 大部分情況下是通過直接指定異常參數(shù)@catch(NSException *e)
{
// 捕獲到異常的處理措施

} @finally {
// 無論有無異常都要執(zhí)行的操作,例如某些資源的釋放等。

}

對于@try代碼塊中出現(xiàn)的異常,會將異常發(fā)送到@catch代碼塊中進行處理。在這種情況下出現(xiàn)的異常情況,不會將異常發(fā)送到系統(tǒng)級別,因此不會引起系統(tǒng)的閃退情況。

接下來寫代碼測試


image.png

捕捉閃退信息如下:


image.png

預先設置對異常的捕獲,不會引起app的閃退。沒有對可能發(fā)生異常的地方進行處理機制,會引起app的閃退。

二、未知異常的捕獲
在默認情況下,系統(tǒng)發(fā)生了未知異常,系統(tǒng)會捕獲該異常并且退出app。發(fā)生異常后,系統(tǒng)會創(chuàng)建一個NSExcetion對象,并且在異常出拋出,等待有接受者,若沒有傳遞給系統(tǒng)處理。那么如何來獲取這個未知異常呢?該問題問的好!利用如下函數(shù)來解決這個問題:

FOUNDATION_EXPORT void NSSetUncaughtExceptionHandler(NSUncaughtExceptionHandler * _Nullable);

該函數(shù)是一個全局的函數(shù),該函數(shù)一般在app開始的時候調用,該函數(shù)的意義:設置未知異常的捕獲函數(shù),參數(shù)是未知異常處理函數(shù)的函數(shù)名,該未知異常處理函數(shù)的模式如下:
typedef void NSUncaughtExceptionHandler(NSException *exception);

未知異常處理函數(shù)的示例

void uncaughtExceptionHandler(NSException *exception) {
    
   // 在app退出前的一些處理任務,系統(tǒng)會等待該函數(shù)的執(zhí)行完畢
    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退出前的一些處理任務,系統(tǒng)會等待該函數(shù)的執(zhí)行完畢,上面代碼中我們進行了線程 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進程。

比較成熟的第三方閃退監(jiān)控平臺:Bugly、友盟等

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
【社區(qū)內容提示】社區(qū)部分內容疑似由AI輔助生成,瀏覽時請結合常識與多方信息審慎甄別。
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發(fā)布,文章內容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

相關閱讀更多精彩內容

友情鏈接更多精彩內容