主要講解Runloop的一些基礎(chǔ)概念;
1. 什么是Runloop?
-
Runloop
是通過內(nèi)部維持事件循環(huán)
來對事件/消息
進行管理的一個對象
; -
Runloop
跟線程是一一對應(yīng)的; -
NSRunLoop
和CFRunLoopRef
是所說的Runloop
的具體類;CFRunLoopRef
是CoreFoundation
框架內(nèi)的C
實現(xiàn)的, 線程安全;NSRunLoop
是基于CFRunloopRef
的封裝,不是線程安全的; - 主線程的
Runloop
是系統(tǒng)默認(rèn)創(chuàng)建啟動的, 子線程的Runloop
默認(rèn)沒有啟動,需要手動獲取;蘋果不允許直接創(chuàng)建Runloop
,它提供了兩個自動獲取的函數(shù):CFRunLoopGetMain()
和CFRunLoopGetCurrent()
;當(dāng)獲取不到時底層再進行創(chuàng)建;
事件循環(huán):沒有消息處理時會處于休眠狀態(tài)避免資源占用(用戶態(tài)->內(nèi)核態(tài));有事件處理時會立刻喚醒(內(nèi)核態(tài)->用戶態(tài)); 當(dāng)沒有消息處理時處于內(nèi)核態(tài)線程阻塞狀態(tài), 注意這種阻塞不占用
CPU
資源(跟用戶寫的while(1)
這種死循環(huán)阻塞是兩個概念);
2. 為什么main函數(shù)能保持不退出?
int main(int argc, char * argv[]) {
@autoreleasepool {
return UIApplicationMain(argc, argv, nil, NSStringFromClass([QNAppDelegate class]));
}
}
main
函數(shù)本質(zhì)上是調(diào)用UIApplicationMain
函數(shù); 在UIApplicationMain
函數(shù)內(nèi)部創(chuàng)建了main runloop
, 根據(jù)runloop
的特點, 它可以不斷的接收處理消息, 處理完事件后繼續(xù)等待; 它就這樣一直這樣在內(nèi)核態(tài)
和用戶態(tài)
之間切換循環(huán)下去 ; 所以main
函數(shù)不會被退出;
3. Runloop的各種Mode?
-
NSDefaultRunLoopMode
默認(rèn)模式, 主線程在這個模式下運行; -
UITrackingRunLoopMode
界面跟蹤模式, 例如滾動UITableview
時將切換到這種模式, 保證滑動時不受其他Mode
影響; -
UIInitializationRunLoopMode
啟動APP時進入的第一個Mode
,啟動完成后不再使用; -
GSEventReceiveRunLoopMode
接受系統(tǒng)內(nèi)部事件的Mode
; NSRunLoopCommonModes
CommonMode
不是實際存在的一種Mode
;
它是同步Source/Timer/Observer
到多個Mode中的一種方案;
Runloop
對象可以包含多個Mode
, 而每個Mode
包含多個timer
, observer
, source
;
知識點:如何解決UITableView上輪播圖在滾動時失效的問題?
主線程的Mode
有兩種模式, 默認(rèn)是NSDefaultRunLoopMode
模式, 當(dāng)滾動tableView
時回切換到UITrackingRunLoopMode
模式, 這時輪播圖的timer
就會失效, 將timer
添加到NSRunLoopCommonModes
可以解決這個問題;
4. Runloop的大致執(zhí)行流程
- 通知
Observers
進入Runloop
; - 通知
Observers
即將處理Timer
; - 通知
Observers
即將處理Sources
; - 處理
Blocks
; - 處理
Source0
, 有可能會再次處理Blocks
; - 如果存在
Source1
, 跳至第8步; - 通知
Observers
開始休眠(等待消息喚醒); - 通知
Observers
結(jié)束休眠(被某個消息喚醒);
8.1 處理Timers
;
8.2 處理GCD Asyn to Main Queue
;
8.3 處理Source1
; - 處理
Blocks
; - 根據(jù)處理結(jié)果決定下一步操作
10.1 回到第2步繼續(xù)執(zhí)行;
10.2 退出Runloop
; - 通知
Observers
退出Runloop
;
參考文章
Apple 一些源碼的下載地址)
用戶態(tài)和內(nèi)核態(tài)
iOS UIApplicationMain函數(shù)做了什么
iOS 深入理解RunLoop
iOS 簡單監(jiān)測iOS卡頓的demo
iOS 多線程技術(shù)之二RunLoop