本文是拜讀 http://blog.ibireme.com/2015/05/18/runloop/ 后的一些個(gè)人見解. 想更加深入地了解請(qǐng)猛戳上面的鏈接.
RunLoop,翻譯過(guò)來(lái),就是一個(gè)不斷循環(huán)的閉環(huán).這個(gè)閉環(huán)不斷地處理任務(wù). 具體流程是處理任務(wù)-休眠-被喚醒處理任務(wù).正如餐廳服務(wù)員可以響應(yīng)客人的需求,在客人不需要服務(wù)的時(shí)候在門外守候,直到再次被召喚.
事實(shí)上,RunLoop就是一個(gè)對(duì)象,這個(gè)對(duì)象管理了其需要處理的事件和消息,并提供了一個(gè)入口函數(shù)來(lái)執(zhí)行一個(gè)doWhile函數(shù),不斷處理任務(wù).線程執(zhí)行了這個(gè)函數(shù)后,就會(huì)一直處于這個(gè)函數(shù)內(nèi)部 "接受消息->等待->處理" 的循環(huán)中,直到這個(gè)循環(huán)結(jié)束(比如傳入 quit 的消息),函數(shù)返回.還是舉餐廳的例子,一旦客人進(jìn)來(lái)餐廳,餐廳就要負(fù)責(zé)調(diào)配服務(wù)員處理客人的要求,直到客人用餐完畢離開.
我們什么時(shí)候會(huì)需要用到RunLoop呢?
在回答這個(gè)問(wèn)題之前,我們得知道更多的信息,其實(shí),每一個(gè)線程都是對(duì)應(yīng)一個(gè)RunLoop的,但是除了主線程的RunLoop,其他RunLoop默認(rèn)是不開啟的.只有我們主動(dòng)獲取他的時(shí)候,才會(huì)開啟.
要了解RunLoop,我們必須知道兩個(gè)對(duì)象:
1,CFRunLoopRef是在Core Foundation里面的,它是一套純C的API,是線程安全的.
2,NSRunLoop則是對(duì)CFRunLoopRef的封裝,它是面對(duì)對(duì)象的API,不是線程安全的.
由于NSRunLoop并不是開源的,我們只能通過(guò)CFRunLoopRef來(lái)研究.通過(guò)http://opensource.apple.com/tarballs/CF/CF-855.17.tar.gz](http://opensource.apple.com/tarballs/CF/CF-855.17.tar.gz可以下載源代碼.
RunLoop 與線程的關(guān)系
首先,iOS 開發(fā)中能遇到兩個(gè)線程對(duì)象: pthread_t 和 NSThread。過(guò)去蘋果有份文檔標(biāo)明了 NSThread 只是 pthread_t 的封裝,但那份文檔已經(jīng)失效了,現(xiàn)在它們也有可能都是直接包裝自最底層的 mach thread。蘋果并沒有提供這兩個(gè)對(duì)象相互轉(zhuǎn)換的接口,但不管怎么樣,可以肯定的是 pthread_t 和 NSThread 是一一對(duì)應(yīng)的。比如,你可以通過(guò) pthread_main_np() 或 [NSThread mainThread] 來(lái)獲取主線程;也可以通過(guò) pthread_self() 或 [NSThread currentThread] 來(lái)獲取當(dāng)前線程。CFRunLoop 是基于 pthread 來(lái)管理的。
蘋果不允許直接創(chuàng)建 RunLoop,它只提供了兩個(gè)自動(dòng)獲取的函數(shù):CFRunLoopGetMain() 和 CFRunLoopGetCurrent()。