1遮婶、概念
RunLoop
與線程關聯(lián)的蝗碎,是一種事件處理環(huán),用來安排和協(xié)調(diào)到來的事件旗扑,目的就是讓其關聯(lián)的線程在有事件到達時時刻保持運行狀態(tài)蹦骑,而當沒有事件需要處理時進入睡眠狀態(tài)從而節(jié)約資源,每一個線程都可以有一個RunLoop
對象與之對應臀防,并且是在第一次獲取它是系統(tǒng)自動創(chuàng)建的眠菇,比如主線程關聯(lián)的RunLoop
,我們都知道程序的入口函數(shù)是main
函數(shù)袱衷,下面是創(chuàng)建工程后Xcode
自動生成的main.m
文件的main
函數(shù)代碼:
int main(int argc, char * argv[]) {
@autoreleasepool {
return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class]));
}
}
該方法執(zhí)行體被autoreleasepool
包圍捎废,所以程序可以使用ARC
來管理內(nèi)存,后面會講解RunLoop
與autoreleasepool
的關系致燥,main
函數(shù)直接返回了UIApplicationMain
函數(shù)登疗,該函數(shù)內(nèi)部就會第一次獲取RunLoop
對象,所以系統(tǒng)就會創(chuàng)建這樣一個RunLoop
對象嫌蚤,因此在沒有滿足特定條件的時候該主線程不會退出谜叹,應用就可以持續(xù)運行而不會退出。
在官方文檔中使用下圖描述RunLoop
模型:
從上圖可以看出一個線程會關聯(lián)一個RunLoop
對象搬葬,RunLoop
對象會一直循環(huán)荷腊,直到超時或收到退出指令。在無限循環(huán)的過程中會一直處理到來的事件急凰,右側將事件分為了兩類女仰,一類是Input sources
這部分包括基于端口的source1
事件,開發(fā)者提交的各種source0
事件抡锈,調(diào)用performSelector:onThread:
方法事件疾忍,還有一類Timer sources
這個就是常用的定時器事件,這些事件在程序運行期間會不斷產(chǎn)生之后會由RunLoop
對象檢測并負責處理相關事件床三。
2一罩、RunLoop
源碼解析
RunLoop
有兩個對象,NSRunLoop
和CFRunLoopRef
撇簿,區(qū)別在于由Core Foundation
框架提供的CFRunLoopRef
是純C語言編寫的聂渊,提供的也是C語言接口,這些接口都是線程安全的四瘫,由Foundation
框架提供的NSRunLoop
是面向?qū)ο蟮暮核裕腔?code>CFRunLoopRef的封裝,提供的都是面向?qū)ο蟮慕涌谡颐郏@些接口不是線程安全的饼暑,Core Foudation
框架是開源的,可以在這個地址下載:Core Foundation開源代碼,本文接下來的內(nèi)容主要是針對該開源代碼進行講解弓叛。
首先彰居,看一下在代碼中如何獲取RunLoop
對象,在Foundation
框架中的NSRunLoop
類提供了如下兩個類屬性:
//獲取當前線程關聯(lián)的RunLoop對象
@property (class, readonly, strong) NSRunLoop *currentRunLoop;
//獲取主線程關聯(lián)的RunLoop對象
@property (class, readonly, strong) NSRunLoop *mainRunLoop
對應的Core Foundation
里提供下面兩個函數(shù)來獲取RunLoop
對象
//獲得當前線程關聯(lián)的RunLoop對象
CFRunLoopGetCurrent();
// 獲得主線程關聯(lián)的RunLoop對象
CFRunLoopGetMain();
具體細節(jié)可以查閱這里:深入理解RunLoop