iOS RunLoop深入淺出

轉(zhuǎn)載自原文,參入自己的了解。

另外有一篇比較好介紹RunLoop與NSTimer之間的關(guān)系的文章,鏈接在這

RunLoop解決什么問(wèn)題

手機(jī)是事件驅(qū)動(dòng)的架構(gòu)。一般來(lái)講,一個(gè)線(xiàn)程一次只能執(zhí)行一個(gè)任務(wù),執(zhí)行完成后線(xiàn)程就會(huì)退出。如果我們需要一個(gè)機(jī)制,讓線(xiàn)程能隨時(shí)處理事件但并不退出
具體來(lái)說(shuō):
1.程序一直運(yùn)行并接受用戶(hù)輸入。
2.決定程序何時(shí)應(yīng)該處理哪些Event。
3.調(diào)節(jié)解耦 被調(diào)方和主調(diào)方解耦
4.節(jié)省CPU時(shí)間

在Cocoa中哪些用到了RunLoop

1.NSTimer
2.UIEvent
3.AutoRelease
4.NSObject(NSDelayPerforming) NSObject (NSThreadPerformAddtion)
5.CA層接口
6.GCD Dispatch_get_main_queue()
7.NSURLConnection AFNetworking

Event Loop 在很多系統(tǒng)和框架里都有實(shí)現(xiàn),比如 Node.js 的事件處理,比如 Windows 程序的消息循環(huán),再比如 OSX/iOS 里的 RunLoop。實(shí)現(xiàn)這種模型的關(guān)鍵點(diǎn)在于:如何管理事件/消息,如何讓線(xiàn)程在沒(méi)有處理消息時(shí)休眠以避免資源占用、在有消息到來(lái)時(shí)立刻被喚醒。

線(xiàn)程和 RunLoop 之間是一一對(duì)應(yīng)的,其關(guān)系是保存在一個(gè)全局的 Dictionary 里。線(xiàn)程剛創(chuàng)建時(shí)并沒(méi)有 RunLoop,如果你不主動(dòng)獲取,那它一直都不會(huì)有。RunLoop 的創(chuàng)建是發(fā)生在第一次獲取時(shí),RunLoop 的銷(xiāo)毀是發(fā)生在線(xiàn)程結(jié)束時(shí)。你只能在一個(gè)線(xiàn)程的內(nèi)部獲取其 RunLoop(主線(xiàn)程除外)
但是并不是說(shuō)一個(gè)Thread只能起一個(gè)RunLoop,可以起很多,但是必須是嵌套的,就是一個(gè)RunLoop,里面可以再嵌套R(shí)unLoop,但是根RunLoop只有一個(gè)。

RunLoopMode是RunLoop的核心,跑RunLoop必須在固定的模式下。
CFRunLoopSource,CFRunLoopTimer,CFRunLoopObserver.
1.CFRunLoopTimer NSTimer是對(duì)CFRunLoopTimer的封裝。
2.CFRunLoopSource 比較抽象的一個(gè)概念,形象講就是數(shù)據(jù)源的抽象類(lèi)。有兩個(gè)version的source:source0,source1.
source0:處理app內(nèi)部事件,app自己負(fù)責(zé)管理(觸發(fā))。如UIEvent,CFSocket。
source1:由RunLoop和系統(tǒng)內(nèi)核管理,mach port驅(qū)動(dòng),如CFPort,CFMessagePort。
如有需要,自己選擇一種source,來(lái)實(shí)現(xiàn)。
CFRunLoopObserver:向外部報(bào)告RunLoop的狀態(tài)的改變,框架中很多機(jī)制都由RunLoopOberserver觸發(fā),如CAAnimation。

RunLoop 對(duì)外的接口

在 CoreFoundation 里面關(guān)于 RunLoop 有5個(gè)類(lèi):
CFRunLoopRef
CFRunLoopModeRef
CFRunLoopSourceRef
CFRunLoopTimerRef
CFRunLoopObserverRef

其中 CFRunLoopModeRef 類(lèi)并沒(méi)有對(duì)外暴露,只是通過(guò) CFRunLoopRef 的接口進(jìn)行了封裝。一個(gè) RunLoop 包含若干個(gè) Mode,每個(gè) Mode 又包含若干個(gè) Source/Timer/Observer。每次調(diào)用 RunLoop 的主函數(shù)時(shí),只能指定其中一個(gè) Mode,這個(gè)Mode被稱(chēng)作 CurrentMode。如果需要切換 Mode,只能退出 Loop,再重新指定一個(gè) Mode 進(jìn)入。這樣做主要是為了分隔開(kāi)不同組的 Source/Timer/Observer,讓其互不影響。

**CFRunLoopSourceRef **是事件產(chǎn)生的地方。Source有兩個(gè)版本:Source0 和 Source1。

  • Source0 只包含了一個(gè)回調(diào)(函數(shù)指針),它并不能主動(dòng)觸發(fā)事件。使用時(shí),你需要先調(diào)用 CFRunLoopSourceSignal(source),將這個(gè) Source 標(biāo)記為待處理,然后手動(dòng)調(diào)用 CFRunLoopWakeUp(runloop) 來(lái)喚醒 RunLoop,讓其處理這個(gè)事件。
  • Source1 包含了一個(gè) mach_port 和一個(gè)回調(diào)(函數(shù)指針),被用于通過(guò)內(nèi)核和其他線(xiàn)程相互發(fā)送消息。這種 Source 能主動(dòng)喚醒 RunLoop 的線(xiàn)程,其原理在下面會(huì)講到。

CFRunLoopTimerRef 是基于時(shí)間的觸發(fā)器,它和 NSTimer 是toll-free bridged 的,可以混用。其包含一個(gè)時(shí)間長(zhǎng)度和一個(gè)回調(diào)(函數(shù)指針)。當(dāng)其加入到 RunLoop 時(shí),RunLoop會(huì)注冊(cè)對(duì)應(yīng)的時(shí)間點(diǎn),當(dāng)時(shí)間點(diǎn)到時(shí),RunLoop會(huì)被喚醒以執(zhí)行那個(gè)回調(diào)。

CFRunLoopObserverRef是觀(guān)察者,每個(gè) Observer 都包含了一個(gè)回調(diào)(函數(shù)指針),當(dāng) RunLoop 的狀態(tài)發(fā)生變化時(shí),觀(guān)察者就能通過(guò)回調(diào)接受到這個(gè)變化。可以觀(guān)測(cè)的時(shí)間點(diǎn)有以下幾個(gè):

typedef CF_OPTIONS(CFOptionFlags, CFRunLoopActivity) {
      kCFRunLoopEntry         = (1UL << 0), // 即將進(jìn)入Loop
      kCFRunLoopBeforeTimers  = (1UL << 1), // 即將處理 Timer
      kCFRunLoopBeforeSources = (1UL << 2), // 即將處理 Source
      kCFRunLoopBeforeWaiting = (1UL << 5), // 即將進(jìn)入休眠
      kCFRunLoopAfterWaiting  = (1UL << 6), // 剛從休眠中喚醒
      kCFRunLoopExit          = (1UL << 7), // 即將退出Loop
};

RunLoopObserver 與 AutoReasePool

  • UIKit通過(guò)RunLoopObserver在RunLoop兩次Sleep之間對(duì)AutoReleasePool進(jìn)行Pop和Push,將這次Loop產(chǎn)生的內(nèi)存池進(jìn)行釋放。

Mode是IOS滑動(dòng)技術(shù)的關(guān)鍵蘋(píng)果公開(kāi)提供的 Mode 有兩個(gè):kCFRunLoopDefaultMode (NSDefaultRunLoopMode) 和 UITrackingRunLoopMode,你可以用這兩個(gè) Mode Name 來(lái)操作其對(duì)應(yīng)的 Mode。

CFRunLoopMode

  • RunLoop在同一時(shí)間必須只能在一種Mode下run
  • RunLoop如果想更換Mode,則必須停止當(dāng)前Loop
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀(guān)點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容