- 運行循環(huán)
RunLoop的基本作用:
- 保持程序的持續(xù)運行
- 處理APP中各種事件(比如:觸摸事件,定時器事件,Selector事件等)
- 能節(jié)省CPU資源,提高程序的性能:該做事的時候就喚醒,沒有事情就睡眠
RunLoop對象
iOS中有2套API來訪問和使用RunLoop
- Foundation框架中的NSRunLoop;
- Core Foundation中的CFRunLoop;
NSRunLoop是基于 CFRunLoopRef 的一層OC包裝,所以要了解RunLoop內(nèi)部結(jié)構(gòu),需要多研究CFRunLoopRef層面的API(Core Foundation層面)
RunLoop與線程
- 每條線程都有唯一的一個與之對應(yīng)的RunLoop對象
- 主線程中的RunLoop由系統(tǒng)自動創(chuàng)建,子線程中RunLoop可以通過手動創(chuàng)建
- RunLoop在線程結(jié)束的時候會被銷毀
獲取RunLoop對象
-
Foundation框架中
[NSRunLoop currentRunLoop];//獲得當(dāng)前線程的RunLoop對象
[NSRunLoop mainRunLoop]; // 獲得主線程的RunLoop對象 Core Foundation框架中
CFRunLoopGetCurrent(); // 獲得當(dāng)前線程的RunLoop對象
CFRunLoopGetMain(); // 獲得主線程的RunLoop對象

RunLoop 內(nèi)部結(jié)構(gòu)

在 RunLoop 可以在不同模式下切換,在每個 Mode 下面都會有 Source Observer Timer,分別是 接收和處理消息源,例如觸摸事件等,觀察者,監(jiān)控者執(zhí)行的活動,例如 進(jìn)入、time時間、休眠、喚醒等活動,time 主要是定時器相關(guān)的任務(wù)。
可以簡單的通過下面的這張邏輯圖了解。

我們以一個button點擊時間為例,我們點擊后,會依次執(zhí)行,到 第五步,如果有 source 進(jìn)入那么會跳到第九步處理喚醒時接收的消息,然后跳回第二步?jīng)]有 timer 事件,就處理 source0 ,如果沒有了事件,就會進(jìn)行線程休眠。
如果有事件點擊或是 time 事件,那么線程會被再次喚醒,執(zhí)行上述的流程。
CFRunLoopSource
RunLoop的數(shù)據(jù)源抽象類(類似于OC中的protocol)
RunLoop定義了兩個版本的source:Source0 和 Source1
Source0:處理的是App內(nèi)部的事件、App自己負(fù)責(zé)管理,如按鈕點擊事件等。
Source1:由RunLoop和內(nèi)核管理,Mach Port驅(qū)動,如CFMachPort、CFMessagePort
Source有兩個版本:Source0 和 Source1。主要的差別是主動和手動的喚醒RunLoop
Source0:只包含了一個回調(diào)(函數(shù)指針),它并不能主動觸發(fā)事件。使用時,你需要先調(diào)用CFRunLoopSourceSignal(source)
,將這個 Source 標(biāo)記為待處理,然后手動調(diào)用CFRunLoopWakeUp(runloop)
來喚醒RunLoop
,讓其處理這個事件。--->加入到RunLoop
得待處理隊列中,手動喚醒RunLoop
Source1 :包含了一個 mach_port 和一個回調(diào)(函數(shù)指針),被用于通過內(nèi)核和其他線程相互發(fā)送消息。這種 Source 能主動喚醒RunLoop
的線程