其實(shí),對于做移動 APP 開發(fā)的同學(xué)來說,質(zhì)量和體驗(yàn)都是同等重要的。一個 APP 應(yīng)用如果經(jīng)常「閃退」,是產(chǎn)品質(zhì)量很差的一個體現(xiàn),那么用戶體驗(yàn)就更不用再提了。

上面是筆者截取的國外一家公司對用戶行為分析漫畫的一個片段,從圖中可以看到,有 80%的用戶會因?yàn)榫W(wǎng)絡(luò)錯誤和崩潰拋棄這個 APP,有 86% 的用戶,如果體驗(yàn)太差,絕對不會第二次使用該 APP。所以開發(fā)一個優(yōu)秀的 APP,性能即生死,一定盡量杜絕「閃退」。
誠然,iOS 上的 APP 閃退有各種各樣的原因,像三方庫不兼容、響應(yīng)超時、內(nèi)存不足都有可能造成 Crash。但更多情況下可能是 APP 程序自身的運(yùn)行邏輯存在問題。比如調(diào)用用了 Objective-C 對象根本不支持的方法(發(fā)送消息),非法內(nèi)存訪問,數(shù)組越界,參數(shù)不符合要求等。
這些問題在調(diào)試階段,我們很容易通過給 Xcode 打斷點(diǎn)來進(jìn)行調(diào)試, 但對于已發(fā)布的 APP,如果想重現(xiàn)并利用上述辦法來解決,恐怕會比較費(fèi)時費(fèi)事。
最有幫助最直接的辦法就是根據(jù)出現(xiàn)問題時的閃退日志,分析和判斷 Crash 的原因,快速準(zhǔn)確的定位和解決。
Crash log
在 iOS 上運(yùn)行的 APP 出現(xiàn) Crash 的時候,通常會生成一個 Crash log,記載問題發(fā)生時的具體狀況。開發(fā)者可以在 iTunes Connect 中特定 APP下找到收集上來的 Crash log。也可以連接電腦,去本地目錄找Mac :~/Library/Logs/CrashReporter/MobileDevice/<DEVICE_NAME> 這個時候你會發(fā)現(xiàn)一大堆的.crash 文件和.ips 文件。

不過筆者還是推薦第三種,通過 Xcode 獲取到崩潰日志,方法是 Xcode->Window->Devices,想必很多開發(fā)者和筆者一樣,也都是用的是這個方法。

通過上面三種方法收集到了 Crash log,但用文本編輯器打開文件是一堆十六進(jìn)制的內(nèi)存地址,你會郁悶的發(fā)現(xiàn)壓根看不懂。這又是另一個話題了。
Crash log 的分析
Crash log 里面包含了 Crash 發(fā)生的 APP、運(yùn)行軟硬件環(huán)境、發(fā)生時間、錯誤類型、方法調(diào)用異常棧、各線程狀態(tài)、寄存器和內(nèi)存信息。
而其中對我們開發(fā)人員來說意義最為重大的,可能就是異常線程的調(diào)用棧. 可惜有些時候,這關(guān)鍵的信息竟然全是 16 進(jìn)制的數(shù)據(jù),所以我們很難看懂。比如:
1CrashDebugInfoTest 0x1000c2b90 0x1000bc000 + 27536
那么要從十六進(jìn)制的地址碼,得到我們代碼中對應(yīng)的方法調(diào)用,就需要結(jié)合調(diào)試信息對 Crash log 進(jìn)行符號化。筆者查看了很多文檔,能符號化 Crash log 無非就 3 種方法:
1. 使用開發(fā)工具庫中自帶的 symbolicatecrash
2. 使用 atos
3. 使用 dwarfdump
前兩種方法方法,都簡單的試了一下,但并沒有覺得有多好用,atos 要想把十六進(jìn)制的地址翻譯為符號,需要每次給 APP 打包時生成的 dSYM 文件,個人覺得很是麻煩。而 symbolicatecrash 也是如此,每次都需要在終端輸入一些命令,也是勞心費(fèi)神!
在這個當(dāng)下這個這個注重效率的時代,筆者不認(rèn)為手動的去做這些事情是好的。如果能借助一些工具去解決事情,那就再好不過了。仔細(xì)找了找,國內(nèi)外還真有一些三方工具能解決這個問題。
國外的比如 New Relic,還有國內(nèi) OneAPM 的Mobile Insight。
他們不僅解析了 Crash log,而且能將你所有的 Crash 進(jìn)行分類,做成可視化的,不僅能直觀的看到造成你 APP 崩潰的代碼行,而且?guī)湍憬y(tǒng)計(jì)出這個崩潰是在哪個iOS 系統(tǒng)和機(jī)型下發(fā)生的,這個崩潰影響了多少你的終端用戶,堆棧信息也一目了然。

起初,筆者也不確定他是否能將所有崩潰類型都能抓到,于是在 Github 上下載了CrashProbe-master,一個崩潰類型相對比較全的開源 Demo 親自測了一下,像常見的像無效內(nèi)存地址,空指針未初始化指針,棧溢出造成的 SEGV:(Segmentation Violation)類型和線程異常造成的EXC_BAD_INSTRUCTION類型的崩潰等十幾種崩潰都抓取到了
,感覺還是很驚訝。立馬和身邊一塊做項(xiàng)目的安卓同事念叨了一下,他導(dǎo)入安卓的SDK 之后,簡單的模擬了幾個 Crash,神奇的是,竟然還有崩潰軌跡,就是在發(fā)生崩潰之前你都進(jìn)行了什么操作,都可以看的到。當(dāng)時,筆者心里就有點(diǎn)不平衡了,為啥 iOS 就沒有,去問了他們的技術(shù)支持,說是下一期就能加上,很是期待啊!備注:本文已經(jīng)得到原作者的同意,授權(quán) OneAPM 技術(shù)博客進(jìn)行轉(zhuǎn)載
OneAPM Mobile Insight 以真實(shí)用戶體驗(yàn)為度量標(biāo)準(zhǔn)進(jìn)行 Crash 分析,監(jiān)控網(wǎng)絡(luò)請求及網(wǎng)絡(luò)錯誤,提升用戶留存。訪問 OneAPM 官方網(wǎng)站感受更多應(yīng)用性能優(yōu)化體驗(yàn),想閱讀更多技術(shù)文章,請?jiān)L問 OneAPM 官方技術(shù)博客。