iOS App運行中遇到Crash的狀況相信你們都遇到過,開發和者測試中遇到了可能很方便的辦法就是直接拿着設備鏈接一下,而後使用Xcode自帶的工具就能夠解析出Crash地址了。對於線上App運行時的Crash收集也有不少好用的第三方工具,具備表明性的就是Crashlytics,經過打包時上傳dSYM文件,收集到的Crash就能夠解析爲可讀的格式了。web
儘管Crashlytics功能已經很強大了,統計出來的Crash信息也足夠詳細,仍是會有一些難纏的問題,例如程序直接就掛在main函數中,剩下的就是系統的調用了。下面就聊了一下咱們App中遇到的幾個難纏的Crash:app
一、屢次彈出AlertView時存在的問題函數
在咱們App中有一些地方由於業務會彈出一些二次確認框,當彈出AlertView時切換到後臺,接着再切到前臺,快速點擊觸發二次確認操做,會再彈出一個AlertView,此時點擊該AlertView後,以前已經彈出的AlertView會恢復出來,再點擊程序就會Crash掉。在iPhone採用相同步驟驗證該問題,發現沒法重現,每次程序切回前臺時,AlertView現場迅速恢復,因而可知該問題是iPad上纔會存在。工具
正常狀況下程序退到後臺時,系統會自動隱藏AlertView,等到下次程序切換到前臺時,若是退出前彈出了AlertView,系統會恢復該AlertView的展現。問題就出如今這兒,系統恢復AlertView的展現時是有延遲的,而非當即恢復。在此時若是再觸發先關時間,彈出新的AlertView,就會損壞中斷的現場,從而致使程序運行狀態出現異常,以後再操做可能就會Crash掉。oop
這個問題當時想到了兩種解決辦法:測試
a、在程序退到後臺以前就對彈出層作默認操做動畫
b、程序中設置標誌,標識當前是否已經彈出AlertView,若是已經彈出,再操做時就不會再彈出AlertViewspa
第一種方法,會存在一些問題,由於有些界面的AlertView彈出之後,點擊默認操做可能會影響view層級,這樣從後臺再回來的時候現場界面發生變化,會給用戶形成沒必要要的困惑。指針
第二種方法,在Apps的基類裏面添加一個標記位,彈出AlertView時置爲YES,關閉AlertView時置爲NO。當前App若是已經彈出了AlertView,則後續操做再也不觸發彈出AlertView的操做,這樣就能避免程序從後臺切回來時快速點擊致使的Crash問題。rest
二、webview動畫引起的Crash問題
在執行自動化測試過程當中,不規律的出現了幾回Crash,沒法找到固定的重現步驟,Crash棧以下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
|
Exception Type: EXC_BAD_ACCESS (SIGSEGV)
Exception Codes: KERN_INVALID_ADDRESS at 0x00000008
Crashed Thread: 0
Thread 0 name: Dispatch queue: com.apple.main-
thread
Thread 0 Crashed:
0 libobjc.A.dylib 0x390b15b0 objc_msgSend + 16
1 UIKit 0x33289182 -[_UIWebViewScrollViewDelegateForwarder forwardInvocation:] + 138
2 CoreFoundation 0x31218616 ___forwarding___ + 622
3 CoreFoundation 0x3116ff64 _CF_forwarding_prep_0 + 20
4 UIKit 0x330d40c2 -[UIScrollView _getDelegateZoomView] + 98
5 UIKit 0x330d3fc0 -[UIScrollView _zoomScaleFromPresentationLayer:] + 24
6 UIKit 0x330d9fec -[UIWebDocumentView _zoomedDocumentScale] + 56
7 UIKit 0x330d6ae8 -[UIWebDocumentView _layoutRectForFixedPositionObjects] + 100
8 UIKit 0x3327b292 -[UIWebDocumentView _updateFixedPositionedObjectsLayoutRectUsingWebThread:synchronize:] + 38
9 UIKit 0x330dc6d4 -[UIWebDocumentView _updateFixedPositioningObjectsLayoutAfterScroll] + 24
10 UIKit 0x330dc6b0 -[UIWebBrowserView _updateFixedPositioningObjectsLayoutAfterScroll] + 52
11 UIKit 0x330dc566 -[UIWebDocumentView _restoreScrollPointForce:] + 502
12 UIKit 0x330dc25c -[UIWebDocumentView _resetForNewPage] + 408
13 UIKit 0x330a84c4 -[UIWebDocumentView layoutSubviews] + 72
14 UIKit 0x330217fe -[UIView(CALayerDelegate) layoutSublayersOfLayer:] + 254
15 QuartzCore 0x32dcbd86 -[CALayer layoutSublayers] + 210
16 QuartzCore 0x32dcb924 CA::Layer::layout_if_needed(CA::Transaction*) + 456
17 QuartzCore 0x32dcc858 CA::Layer::layout_and_display_if_needed(CA::Transaction*) + 12
18 QuartzCore 0x32dcc23e CA::Context::commit_transaction(CA::Transaction*) + 234
19 QuartzCore 0x32dcc04c CA::Transaction::commit() + 312
20 UIKit 0x330278e6 _afterCACommitHandler + 122
21 CoreFoundation 0x311eb6ca __CFRUNLOOP_IS_CALLING_OUT_TO_AN_OBSERVER_CALLBACK_FUNCTION__ + 18
22 CoreFoundation 0x311e99bc __CFRunLoopDoObservers + 272
23 CoreFoundation 0x311e9d12 __CFRunLoopRun + 738
24 CoreFoundation 0x3115ceb8 CFRunLoopRunSpecific + 352
25 CoreFoundation 0x3115cd44 CFRunLoopRunInMode + 100
26 GraphicsServices 0x34d262e6 GSEventRunModal + 70
27 UIKit 0x330722fc UIApplicationMain + 1116
28 MyApp 0x0000fc60 main (main.m:15)
29 libdyld.dylib 0x394edb1c start + 0
|
Crash棧咋一看,掛在系統的API調用上,再仔細看一下報EXC_BAD_ACESS錯誤,應該是對象被釋放後致使了野指針調用問題。仔細查看Apps中調用到Webview的地方發現,使用方法沒什麼問題。網上搜索了一下發現,該問題多是因爲webview在動畫中,持有者(VC)已經被釋放致使的。
解決辦法:在全部持有Webview的對象釋放前都添加了Webview的delegate置空操做。
在自動化測試中tableview,scrollview也遇到了Webview類似的問題,所以就在程序中相關地方都作了保護處理,以後自動化測試中該類問題沒有再出現過。
一點感想:拿到Crash棧,一看是掛在系統調用,估計就不想花時間解決了。有時候堅持一下,多看一下子,多想一下,嘗試去Google上搜一下Crash信息中的一些字段,或許別人也有遇到過相同或者類似的問題,說不定獲得啓發從而解決了一個看似無法解決的問題。