前言
查看閃退日志的步驟
(1)獲取閃退日志
(2)獲取symbolicatecrash 腳本
(3)獲取閃退日志對(duì)應(yīng)的符號(hào)表(.dSYM 文件)
(4)解析閃退日志
蘋果官網(wǎng)關(guān)于閃退日志的介紹:
https://developer.apple.com/library/content/technotes/tn2151/_index.html
Understanding and Analyzing Application Crash Reports
When an application crashes, a crash report is created which is very useful for understanding what caused the crash. This document contains essential information about how to symbolicate, understand, and interpret crash reports.
理解以及分析閃退日志:
當(dāng)app發(fā)生閃退的時(shí)候,會(huì)創(chuàng)建閃退日志,這對(duì)于我們查找閃退原因是非常有用的。
一、獲取iOS 設(shè)備上閃退日志

1、(windows 電腦)使用pp助手獲取閃退日志 將iOS 設(shè)備和winwods電腦連接,打開pp助手,查看閃退日志,將閃退日志導(dǎo)出,導(dǎo)出后會(huì)得到一個(gè)后綴為ips的文件。修改后綴名為.crash。
2、(MAC電腦)將設(shè)備連接到電腦,進(jìn)入 ~/Library/Logs/CrashReporter/MobileDevice 文件夾可以獲得閃退日志。
3、通過(guò)Xcode 獲取閃退日志 :打開Xcode > window > Devices > view device logs 就可以查看閃退日志。
4、獲取已經(jīng)發(fā)布到appStore上和上傳到testflight 上的包,在用戶和測(cè)試員設(shè)備上發(fā)生的閃退日志。打開Xcode>Window>organizer 選擇 crashes 標(biāo)簽。然后我們就可以看見一個(gè)閃退日志列表。選中某一個(gè)閃退日志右鍵顯示包內(nèi)容,然后進(jìn)入DistributionInfos>all>logs。就可以看見閃退日志了。 (?? 如果發(fā)布的時(shí).dysm 文件也上傳到了apple 的服務(wù)器,一般點(diǎn)擊 open in project 就會(huì)直接定位到項(xiàng)目閃退的位置。
蘋果官網(wǎng)關(guān)于發(fā)布到市場(chǎng)和testflight 上的閃退日志的介紹
https://developer.apple.com/library/content/documentation/IDEs/Conceptual/AppDistributionGuide/AnalyzingCrashReports/AnalyzingCrashReports.html )
二、閃退日志的組成
{"app_name":"XXXAPP",
"app_version":"6.0.0",
"bundleID":"com.XXXAPP.app",
"adam_id":0,"os_version":
"iPhone OS 8.3 (12F70)",
"slice_uuid":"xxxxxx",
"share_with_app_devs":false,"build_version":"17040602528","is_first_party":false,"bug_type":"109","name":"XXXAPP"}
Incident Identifier: A7427996-4DA4-457E-B868-990F0EF557F8
CrashReporter Key: 0bc6652b6f3c9d95786ce42bd4746d49fe7071a6
Hardware Model: iPhone7,1
Process: XXXAPP [12119]
Path: /private/var/mobile/Containers/Bundle/Application/271EC22E-C2EC-4256-A7DD-480F78C1EE52/XXXAPP.app/XXXAPP
Identifier: com.XXXAPP.app
Version: 17040602528 (6.0.0)
Code Type: ARM-64 (Native)
Parent Process: launchd [1]
Date/Time: 2017-04-10 13:35:15.100 +0800
Launch Time: 2017-04-10 13:18:14.005 +0800
OS Version: iOS 8.3 (12F70)
Report Version: 105
Exception Type: EXC_BAD_ACCESS (SIGSEGV)
Exception Subtype: KERN_INVALID_ADDRESS at 0x0000000000000010
Triggered by Thread: 0
Thread 0 name: Dispatch queue: com.apple.main-thread
Thread 0 Crashed:
0 libobjc.A.dylib 0x0000000194453bd0 0x194438000 + 113616
1 XXXAPP 0x0000000100944330 0x10006c000 + 9274160
2 XXXAPP 0x0000000100935014 0x10006c000 + 9211924
3 XXXAPP 0x0000000100952be4 0x10006c000 + 9333732
4 XXXAPP 0x000000010099af78 0x10006c000 + 9629560
5 XXXAPP 0x00000001009af4a0 0x10006c000 + 9712800
6 UIKit 0x000000018766bfbc 0x187644000 + 163772
7 UIKit 0x00000001876d82d4 0x187644000 + 606932
8 UIKit 0x00000001876d823c 0x187644000 + 606780
9 UIKit 0x0000000187648710 0x187644000 + 18192
10 CoreFoundation 0x0000000182bcc2a0 0x182aec000 + 918176
11 CoreFoundation 0x0000000182bc922c 0x182aec000 + 905772
12 CoreFoundation 0x0000000182bc960c 0x182aec000 + 906764
13 CoreFoundation 0x0000000182af52d0 0x182aec000 + 37584
14 GraphicsServices 0x000000018c30b6f8 0x18c300000 + 46840
15 UIKit 0x00000001876bafa8 0x187644000 + 487336
16 XXXAPP 0x00000001006c6468 0x10006c000 + 6661224
17 libdyld.dylib 0x0000000194abea04 0x194abc000 + 10756
| 關(guān)鍵字 | 含義 |
|---|---|
| Incident Idnetifier | 閃退的唯一標(biāo)示 |
| CrashReporter Key | 設(shè)備標(biāo)識(shí)相對(duì)應(yīng)的唯一鍵值(并非真正的設(shè)備的UDID,蘋果為了保護(hù)用戶隱私iOS6以后已經(jīng)無(wú)法獲取)。通常同一個(gè)設(shè)備上同一版本的App發(fā)生Crash時(shí),該值都是一樣的。 |
| Hardware Model | 設(shè)備類型 |
| Version | 當(dāng)前App的版本號(hào),由Info.plist中的兩個(gè)字段組成,CFBundleShortVersionString and CFBundleVersion ![]() buildnum.png
|
Code Type | 當(dāng)前App的CPU架構(gòu)
Exception Types | 異常類型
Exception Subtype | 異常子類型
?? 每次打包的時(shí)候,一定要確保 Version的唯一性。
常見的異常類型
| 異常 | 描述 | 注釋 |
|---|---|---|
| EXC_BAD_ACCESS | Bad Memory Access | Access to “bad” memory address. The “bad” can be either “the address does not exist” or “the app does not have privilege to access to”. So it usually ties to SIGBUS and SIGSEGV. |
| EXC_CRASH | Abnormal Exit | Usually tie to SIGABRT, meaning the app exits abnormally by detecting some uncaught exceptions through the code. |
| EXC_BREAKPOINT | Trace / breakpoint Trap | Usually tie to SIGTRAP. Can be triggered either by your own code or NSExceptions being thrown. |
| EXC_GUARD | Violated Guarded Resource Protection | Be triggered by violating a guarded resource protection, like “certain file descriptor”. |
| EXC_BAD_INSTRUCTION | Illegal Instruction | Usually related to certain illegal or undefined instruction or operand. |
| EXC_RESOURCE | Resource Limit | App crashes by hitting resource consumption limit. |
| 00000020 | Hexadecimal Exception Type | Not “OS Kernel” exception. |
參考文章
http://www.5neo.be/understanding-ios-exception-types/
三、符號(hào)化閃退日志
1、獲取symbolicatecrash 工具
打開終端輸入下面的命令
find /Applications/Xcode.app -name symbolicatecrash -type f
或者
find /Applications/Xcode.app -name symbolicatecrash
我們會(huì)得到這樣一個(gè)路徑
/Applications/Xcode.app/Contents/Developer/Platforms/AppleTVSimulator.platform/Developer/Library/PrivateFrameworks/DVTFoundation.framework/symbolicatecrash
打開finder 前往這個(gè)路徑

拷貝 symbolicatecrash
2、獲取 .dysm 文件
打開Xcode 選擇 window > organizer > 選擇Archives 標(biāo)簽 。我們可以看到我們打完包的一個(gè)列表。我們可以看見閃退日志的信息里面有這樣一個(gè)版本號(hào)的信息 Version: 17040602528 (6.0.0),,找到打包列表里面和這個(gè) build 號(hào)相對(duì)應(yīng)的.xcarchive文件,然后右鍵show in finder
顯示包內(nèi)容進(jìn)入dSYMs 文件夾>拷貝項(xiàng)目相應(yīng)的 .dsyM 文件
3、將.crash 文件 和 拷貝出來(lái)的 symbolicatecrash 腳本 以及 閃退日志對(duì)應(yīng)的 .dsyM 文件拷貝到同一個(gè)文件夾里面。然后打開終端進(jìn)入這個(gè)文件夾。

[圖片上傳中...(213123123.png-912e98-1513584168018-0)]
cd /Users/StarHui/Desktop/20170417crash/crash1
注釋:cd /Users/你電腦的用戶名/存放上述三個(gè)文件的文件夾路徑
然后輸入(只需要輸入一次)
export DEVELOPER_DIR="/Applications/XCode.app/Contents/Developer"
然后輸入
./symbolicatecrash crash1.crash xxx.app.dSYM > crashLog3.txt
等命令執(zhí)行完成之后,我們可以在剛才的文件夾下面發(fā)現(xiàn) crashLog3.txt 符號(hào)化后的閃退日志。
crash1.crash 閃退日志
xxx.app.dSYM dySM 文件
符號(hào)化后的日志 crashLog3.txt
我們可以在已經(jīng)符號(hào)化后的閃退日志里面看到我們代碼出錯(cuò)的地方。(可以直接定位到閃退發(fā)生在那個(gè)文件的那一行代碼)

