如果不借助第三方框架,要收集ios app的crash log是一件很困難的事情。有2個辦法:
第一個辦法是要求用戶打開“診斷與用量”中的自動發送,然後如果APP崩潰了,ios會彈出提示框,用戶確認之後,crash log會自動發送到蘋果後台,然後用開發者賬號登陸上去,可以拿到crash log
第二個辦法是將device,同步到iTunes之後,再從pc上拿到crash log,再發送
詳細步驟見:
how to get crash log
syncing with iTunes
可以看到,2種方式都不太靠譜,所以現實的方法還是使用第三方框架,比如Crashlytics之類的。在app崩潰的時候,會自動采集crash log
拿到crash log以後,還要解決怎麼讀的問題。原始的crash log是不可讀的,內容類似這樣:
Last Exception Backtrace:
(0x313b1e83 0x3ba4d6c7 0x312e7d95 0xcef95 0xce843 0x7c6d1 0x3bf320c3 0x3bf377d9 0x3bf379c5 0x3c061dff 0x3c061cc4)
Thread 0:
0 libsystem_kernel.dylib 0x3bfeaa84 0x3bfea000 + 2692
1 libsystem_kernel.dylib 0x3bfea87d 0x3bfea000 + 2173
2 CoreFoundation 0x3137c555 0x312dd000 + 652629
3 CoreFoundation 0x3137acbb 0x312dd000 + 646331
4 CoreFoundation 0x312e546d 0x312dd000 + 33901
5 CoreFoundation 0x312e524f 0x312dd000 + 33359
6 GraphicsServices 0x35fe62e7 0x35fdf000 + 29415
7 UIKit 0x33b9a841 0x33b2b000 + 456769
這樣的一份日志,即使拿到了也幾乎沒有意義,對定位問題沒有幫助,所以需要將crash log做符號化
一般來說,任何app的crash log在xcode中都能部分符號化,也就是UIKit,CoreFoundation這種系統級的庫,但是要想真正得到完全符號化的crash log,需要滿足2個條件:
1、有app的二進制包
2、有編譯此二進制包時得到的dSYM文件
只要是曾經編譯過該app的機器,應該都滿足這個條件。然後把拿到的.ips或.crash文件導入到xcode,就會自動符號化了,完全符號化以後,crash log就可讀了:
Last Exception Backtrace:
0 CoreFoundation 0x183cba950 __exceptionPreprocess + 132
1 libobjc.A.dylib 0x1905701fc objc_exception_throw + 60
2 CoreFoundation 0x183bbc218 -[__NSArrayI objectAtIndex:] + 204
3 TestNotification 0x100029cfc -[MainViewController clicked1] (MainViewController.m:42)
4 UIKit 0x186cb90c8 -[UIApplication sendAction:to:from:forEvent:] + 100
5 UIKit 0x186cb905c -[UIApplication sendAction:toTarget:fromSender:forEvent:] + 24
6 UIKit 0x186ca2538 -[UIControl _sendActionsForEvents:withEvent:] + 376
7 UIKit 0x186cb8a5c -[UIControl touchesEnded:withEvent:] + 584
8 UIKit 0x186cb86f0 -[UIWindow _sendTouchesForEvent:] + 692
9 UIKit 0x186cb3388 -[UIWindow sendEvent:] + 1172
10 UIKit 0x186c84b68 -[UIApplication sendEvent:] + 256
11 UIKit 0x186c82c58 _UIApplicationHandleEventQueue + 8500
12 CoreFoundation 0x183c7b044 __CFRUNLOOP_IS_CALLING_OUT_TO_A_SOURCE0_PERFORM_FUNCTION__ + 24
13 CoreFoundation 0x183c7a3a0 __CFRunLoopDoSources0 + 256
14 CoreFoundation 0x183c78638 __CFRunLoopRun + 632
15 CoreFoundation 0x183bb96d0 CFRunLoopRunSpecific + 452
16 GraphicsServices 0x189845c0c GSEventRunModal + 168
17 UIKit 0x186ceafdc UIApplicationMain + 1156
18 TestNotification 0x100029990 main (main.m:16)
19 libdyld.dylib 0x190b63aa0 start + 4
Thread 0 Crashed:
0 libsystem_kernel.dylib 0x0000000190c5e58c __pthread_kill + 8
1 libsystem_c.dylib 0x0000000190bf2804 abort + 108
2 libc++abi.dylib 0x000000018fe18990 abort_message + 84
3 libc++abi.dylib 0x000000018fe35c28 default_terminate_handler() + 296
4 libobjc.A.dylib 0x00000001905704d0 _objc_terminate() + 124
5 libc++abi.dylib 0x000000018fe33164 std::__terminate(void (*)()) + 12
6 libc++abi.dylib 0x000000018fe32d38 __cxa_rethrow + 140
7 libobjc.A.dylib 0x00000001905703a4 objc_exception_rethrow + 40
8 CoreFoundation 0x0000000183bb9748 CFRunLoopRunSpecific + 572
9 GraphicsServices 0x0000000189845c08 GSEventRunModal + 164
10 UIKit 0x0000000186ceafd8 UIApplicationMain + 1152
11 TestNotification 0x000000010002998c main (main.m:16)
12 libdyld.dylib 0x0000000190b63a9c start + 0
line3可以很清楚地看出,崩潰發生在MainViewController的42行,關於dSYM的介紹,詳見這篇文章:crash log
所以最好的辦法,還是使用第三方框架。以Crashlytics為例,它會要求在xcode的編譯過程中集成一個腳本,這個腳本的作用大致上是把二進制包和dSYM發送到Crashlytics的網站上,這樣當Crashlytics拿到crash log以後,也就可以進行完全的符號化了