iOS卡頓檢測
卡頓問題,就是在主執行緒上無法響應使用者互動的問題。如果一個App時不時地就給你卡
一下,有時還長時間無響應,這時你還願意繼續用它嗎?所以說,卡頓問題對App的傷
害是巨大的,也是我們必須要重點解決的一個問題。
現在,我們先來看一下導致卡頓問題的幾種原因:
●複雜UI、圖文混排的繪製量過大;
●在主執行緒.上做網路同步請求;
●在主執行緒做大量的I0操作;
●運算量過大,CPU持續高佔用;
●死鎖和主子執行緒搶鎖。
那麼,我們如何監控到什麼時候會出現卡頓呢?是要監視FPS嗎?
FPS是一秒顯示的幀數,也就是-秒內畫面變化數量。如果按照動畫片來說,動畫片的
FPS就是24,是達不到60滿幀的。也就是說,對於動畫片來說,24幀時雖然沒有60
幀時流暢,但也已經是連貫的了,所以並不能說24幀時就算是卡住了。
由此可見,簡單地通過監視FPS是很難確定是否會出現卡頓問題了,所以我就果斷棄了
誦過監視FPS來監控卡頓的方案
RunLoop原理
對於iOS開發來說,監控卡頓就是要去找到主執行緒上都做了哪些事兒。我們都知道,執行緒的訊息事件是依賴於NSRunL oop的,所以從NSRunLoop入手,就可以知道主執行緒上都呼叫了哪些方法。我們通過監聽NSRunL oop的狀態,就能夠發現呼叫方法是否執行時間過長,從而判斷出是否會出現卡頓。所以,我推薦的監控卡頓的方案是:通過監控RunLoop的狀態來判斷是否會出現卡頓。RunLoop是iOs開發中的一個基礎概念,為了幫助你理解並用好這個物件,接下來我會先和你介紹一下它可以做哪些事兒,以及它為什麼可以做成這些事兒。RunLoop這個物件,在ios裡由CFRunLoop實現。簡單來說,RunL oop是用來監聽輸入源,進行排程處理的。這裡的輸入源可以是輸入裝置、網路、週期性或者延遲時間、非同步回撥。RunL oop會接收兩種型別的輸入源: -種是來自另一個執行緒或者來自不同應用的非同步訊息;另一種是來自預訂時間或者重複間隔的同步事件。RunLoop的目的是,當有事件要去處理時保持執行緒忙,當沒有事件要處理時讓執行緒進入休眠。所以,瞭解RunL oop原理不光能夠運用到監控卡頓.上,還可以提高使用者的互動體驗。通過將那些繁重而不緊急會大量佔用CPU的任務(比如圖片載入), 放到空閒的RunLoop模式裡執行,就可以避開在UITrackingRunL oopMode這個RunL _oop模式時是執行。UITrackingRunL oopMode是使用者進行滾動操作時會切換到的RunL oop模式,避免在這個RunL _oop模式執行繁重的CPU任務,就能避免影響使用者互動操作上體驗。
class func checkfps(){ var runLoopActivity:CFRunLoopActivity = .allActivities let runLoopObserver = CFRunLoopObserverCreateWithHandler(kCFAllocatorDefault, CFRunLoopActivity.allActivities.rawValue, true, CFIndex.init(bitPattern: 2000000 - 1)) { (Observer, Activity) in runLoopActivity= Activity var timeoutCount = Date().timeIntervalSince1970 if (runLoopActivity == .beforeWaiting) { timeoutCount = Date().timeIntervalSince1970 } if (runLoopActivity == .afterWaiting) { let new = Date().timeIntervalSince1970 //100毫秒 if new - timeoutCount > 0.01{ let symb = Thread.callStackSymbols print("---------3s-----------\(symb)") } } } CFRunLoopAddObserver(CFRunLoopGetCurrent(), runLoopObserver, CFRunLoopMode.commonModes) }