RunLoop
1、概念
RunLoop是通過內(nèi)部維護(hù)的事件循環(huán)谎懦,來對事件/消息進(jìn)行管理的一個對象
2姨伤、事件循環(huán):
沒有消息需要處理時,休眠以避免資源占用
有消息需要處理時贩幻,立刻被喚醒
3轿腺、數(shù)據(jù)結(jié)構(gòu)
NSRunLoop是不開源的两嘴,CFRunLoop是開源的
- CFRunLoop
- CFRunLoopMode
-
CFRunLoopSource
APP運行的過程其實就是處理各種事件的過程,那么族壳,如果讓大家把事件進(jìn)行分類憔辫,大家會分成幾類?分類的方式有很多仿荆,但一定會有下面這幾種:
系統(tǒng)層事件贰您、應(yīng)用層事件、特殊事件拢操。(這只是為了大家理解source1和source0舉得一個不嚴(yán)謹(jǐn)?shù)睦咏跻啵蠹也灰谝饧?xì)節(jié))source0基本就是應(yīng)用層事件,其中source1基本就是系統(tǒng)事件令境。復(fù)雜點說:
Source0 :非基于Port的 處理事件杠园,什么叫非基于Port的呢?就是說你這個消息不是其他進(jìn)程或者內(nèi)核直接發(fā)送給你的舔庶。(performSelector:onThread:)
Source1 :基于mach_Port的,來自系統(tǒng)內(nèi)核或者其他進(jìn)程或線程的事件抛蚁,可以主動喚醒休眠中的RunLoop(iOS里進(jìn)程間通信開發(fā)過程中我們一般不主動使用)。mach_port大家就理解成進(jìn)程間相互發(fā)送消息的一種機制就好惕橙。(基于Port的線程間通信瞧甩、系統(tǒng)事件捕捉)
-
簡單舉個例子:一個APP在前臺靜止著,此時弥鹦,用戶用手指點擊了一下APP界面肚逸,那么過程就是下面這樣的:
我們觸摸屏幕,先摸到硬件(屏幕),屏幕表面的事件會先包裝成Event, Event先告訴source1(mach_port),source1喚醒RunLoop, 然后將事件Event分發(fā)給source0,然后由source0來處理惶凝。
CFRunLoopSource
CFRunLoopTimer
-
CFRunLoopObserver
可以觀測6個時間點
kCFRunLoopEntry 進(jìn)入RunLoop
kCFRunLoopBeforeTimers 即將處理Timers一些事件
kCFRunLoopBeforeSources 即將處理Sources一些事件
kCFRunLoopBeforeWaiting 即將進(jìn)入休眠 即將從用戶態(tài)->內(nèi)核態(tài)切換
kCFRunLoopAfterWaiting 內(nèi)核態(tài)->用戶態(tài)切換后的不久
kCFRunLoopExit RunLoop退出
4吼虎、RunLoop的Mode
- 如果運行在一個Mode上犬钢,只能接受當(dāng)前Mode的事件苍鲜,其他Mode不會運行
- CommonMode的特殊性
5、事件循環(huán)的實現(xiàn)機制
- 啟動會調(diào)用CFRunLoopRun( )方法
??:main函數(shù)調(diào)用后會調(diào)用UIApplicationMain方法玷犹,方法內(nèi)部會啟動主線程的RunLoop混滔,經(jīng)過一系列處理,主線程的RunLoop處于休眠狀態(tài)歹颓,此時點擊一下屏幕會產(chǎn)生一個mach-port坯屿,會轉(zhuǎn)換成一個Source1,喚醒主線程巍扛,然后運行處理领跛,當(dāng)程序被殺死就會退出RunLoop,線程被殺死撤奸。
6吠昭、RunLoop的核心
7喊括、RunLoop與NSTimer
- void CFRunLoopAddTimer(runLoop, timer, commonMode)
- void __CFRunLoopAddItemToCommonModes(const void *value, void *ctx)
8、RunLoop與多線程
- 常駐線程
獲取當(dāng)前線程的RunLoop矢棚,如果當(dāng)前線程沒有RunLoop會自動創(chuàng)建一個
[NSRunLoop currentRunLoop];
- 創(chuàng)建一個常駐線程