Hi,runloop 交個(gè)朋友吧

developer:hi,runloop 初次見(jiàn)面,交個(gè)朋友吧?
runloop?。耗愫茫芨吲d認(rèn)識(shí)你!

developer:我先自我介紹一下,我叫iOS Developer,你呢?
runloop?。何医衦unloop,你的有些同伴叫我跑圈,我覺(jué)得叫我循環(huán)運(yùn)行比較合適!

developer:我聽(tīng)我的同伴說(shuō)你有點(diǎn)不是很好相處啊,是不是真的?
runloop?。翰粫?huì)吧,我只是喜歡在幕后工作,并不是很愛(ài)拋頭露面而已!

developer:那你的主要工作內(nèi)容都是哪些呢?
runloop?。何野??主要是為了讓程序一直處于運(yùn)行狀態(tài),同時(shí)在運(yùn)行的狀態(tài)下處理一系列的事件,比如觸摸事件定時(shí)器事件、selecter事件,在這樣的高強(qiáng)度的工作下還得維持良好的狀態(tài)!

developer:聽(tīng)起來(lái)很屌的樣子!跟我說(shuō)說(shuō)你跟線(xiàn)程的關(guān)系吧,聽(tīng)說(shuō)你兩是生死相依的兄弟!
runloop?。壕€(xiàn)程啊,我兩誰(shuí)也離不開(kāi)誰(shuí),他出生了我也就誕生了,當(dāng)他被銷(xiāo)毀的時(shí)候我也就撲街了。

developer:那平時(shí)我們拜訪線(xiàn)程挺容易的,要怎么去拜訪你呢?
runloop :有兩種方式
1、Foundation框架下的NSRunLoop
2、Core Foundation框架下得CFRunLoopRef
不論NSRunLoop和CFRunLoopRef都代表著我

[NSRunLoop currentRunLoop]; // 獲得當(dāng)前線(xiàn)程的RunLoop對(duì)象
[NSRunLoop mainRunLoop]; // 獲得主線(xiàn)程的RunLoop對(duì)象
CFRunLoopGetCurrent(); // 獲得當(dāng)前線(xiàn)程的RunLoop對(duì)象
CFRunLoopGetMain(); // 獲得主線(xiàn)程的RunLoop對(duì)象

相關(guān)類(lèi)

看到這張圖沒(méi)?
這張圖就代表著一個(gè)完整的runloop,每一個(gè)runloop中都包含以下5個(gè)類(lèi):
CFRunLoopRef
CFRunLoopModeRef
CFRunLoopSourceRef
CFRunLoopTimerRef
CFRunLoopObserverRef
如果沒(méi)有這5個(gè)類(lèi),runloop將會(huì)直接退出

developer:能詳細(xì)的介紹以下他們嗎?
runloop :當(dāng)然。

CFRunLoopModeRef
CFRunLoopModeRef 類(lèi)并沒(méi)有對(duì)外暴露,只是通過(guò) CFRunLoopRef 的接口進(jìn)行了封裝。
CFRunLoopModeRef代表RunLoop的運(yù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,讓其互不影響。

系統(tǒng)默認(rèn)注冊(cè)了5個(gè)Mode:
kCFRunLoopDefaultMode:App的默認(rèn)Mode,通常主線(xiàn)程是在這個(gè)Mode下運(yùn)行
UITrackingRunLoopMode:界面跟蹤 Mode,用于 ScrollView 追蹤觸摸滑動(dòng),保證界面滑動(dòng)時(shí)不受其他 Mode 影響
UIInitializationRunLoopMode: 在剛啟動(dòng) App 時(shí)第進(jìn)入的第一個(gè) Mode,啟動(dòng)完成后就不再使用
GSEventReceiveRunLoopMode: 接受系統(tǒng)事件的內(nèi)部 Mode,通常用不到
kCFRunLoopCommonModes: 這是一個(gè)占位用的Mode,不是一種真正的Mode

CFRunLoopSourceRef
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ā)送消息。

CFRunLoopObserverRef
CFRunLoopObserverRef 是觀察者,每個(gè) Observer 都包含了一個(gè)回調(diào)(函數(shù)指針),當(dāng) RunLoop 的狀態(tài)發(fā)生變化時(shí),觀察者就能通過(guò)回調(diào)接受到這個(gè)變化??梢杂^測(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
};

上面的 Source/Timer/Observer 被統(tǒng)稱(chēng)為 mode item,一個(gè) item 可以被同時(shí)加入多個(gè) mode。但一個(gè) item 被重復(fù)加入同一個(gè) mode 時(shí)是不會(huì)有效果的。如果一個(gè) mode 中一個(gè) item 都沒(méi)有,則 RunLoop 會(huì)直接退出,不進(jìn)入循環(huán)。

使用

- (void)observer{ 
// 創(chuàng)建observer CFRunLoopObserverRef observer = CFRunLoopObserverCreateWithHandler(CFAllocatorGetDefault(), kCFRunLoopAllActivities, YES, 0, ^(CFRunLoopObserverRef observer, CFRunLoopActivity activity) { 
NSLog(@"----監(jiān)聽(tīng)到RunLoop狀態(tài)發(fā)生改變---%zd", activity); 
}); 
// 添加觀察者:監(jiān)聽(tīng)RunLoop的狀態(tài) 
CFRunLoopAddObserver(CFRunLoopGetCurrent(), observer, kCFRunLoopDefaultMode); 
// 釋放Observer 
CFRelease(observer);}

特別注意

/* CF的內(nèi)存管理(Core Foundation) 
1.凡是帶有Create、Copy、Retain等字眼的函數(shù),創(chuàng)建出來(lái)的對(duì)象,都需要在最后做一次release * 比如CFRunLoopObserverCreate 
2.release函數(shù):CFRelease(對(duì)象); 
*/

CFRunLoopTimerRef
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)。

RunLoop 的內(nèi)部邏輯
根據(jù)蘋(píng)果在文檔里的說(shuō)明,RunLoop 內(nèi)部的邏輯大致如下:


可以看到,實(shí)際上 RunLoop 就是這樣一個(gè)函數(shù),其內(nèi)部是一個(gè) do-while 循環(huán)。當(dāng)你調(diào)用 CFRunLoopRun() 時(shí),線(xiàn)程就會(huì)一直停留在這個(gè)循環(huán)里;直到超時(shí)或被手動(dòng)停止,該函數(shù)才會(huì)返回。

developer:那我應(yīng)該怎么樣勞煩你去處理一些問(wèn)題呢?
runloop :解密-神秘的RunLoop這里有記錄怎么去使用runloop

developer:如何才能與你深交呢?
runloop :深入理解RunLoop

最后編輯于
?著作權(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)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

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

  • 轉(zhuǎn)自http://blog.ibireme.com/2015/05/18/runloop 深入理解RunLoop ...
    飄金閱讀 1,087評(píng)論 0 4
  • 轉(zhuǎn)自bireme,原地址:https://blog.ibireme.com/2015/05/18/runloop/...
    乜_啊_閱讀 1,682評(píng)論 0 5
  • 目錄: App啟動(dòng)原理 RunLoop 的概念 RunLoop 與線(xiàn)程的關(guān)系 RunLoop 對(duì)外的接口 RunL...
    jiodg45閱讀 975評(píng)論 0 6
  • RunLoop 的概念 一般來(lái)講,一個(gè)線(xiàn)程一次只能執(zhí)行一個(gè)任務(wù),執(zhí)行完成后線(xiàn)程就會(huì)退出。如果我們需要一個(gè)機(jī)制,讓線(xiàn)...
    Mirsiter_魏閱讀 677評(píng)論 0 2
  • 原文地址:http://blog.ibireme.com/2015/05/18/runloop/ RunLoop ...
    大餅炒雞蛋閱讀 1,271評(píng)論 0 6

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