iOS開發(fā):RunLoop的基本知識(shí)

什么是RunLoop

從字面意思看是 運(yùn)行循環(huán) 跑圈

基本作用:保持程序的持續(xù)運(yùn)行 處理App中的各種事件(比如觸摸事件、定時(shí)器事件、Selector事件 節(jié)省CPU資源,提高程序性能:該做事時(shí)做事,該休息時(shí)休息 ......

如果沒有RunLoop

沒有RunLoop的情況下,第三行后程序就結(jié)束了

沒有RunLoop的情況下,第三行后程序就結(jié)束了

如果有了RunLoop

有了RunLoop?,程序執(zhí)行

有了RunLoop,由于main函數(shù)里面啟動(dòng)了個(gè)runLoop,所以程序并不會(huì)馬上退出,保持持續(xù)運(yùn)行狀態(tài)。其實(shí)RunLoop里面是有個(gè)do-while循環(huán)的,保持程序一直運(yùn)行下去。

main函數(shù)中的RunLoop

main函數(shù)中的RunLoop

第14行的UIApplicationMain函數(shù)內(nèi)部就啟動(dòng)了一個(gè)RunLoop, 所以UIApplicationMain函數(shù)一直沒有返回,保持了程序的持續(xù)運(yùn)行 這個(gè)默認(rèn)啟動(dòng)的RunLoop是跟主線程相關(guān)聯(lián)的

RunLoop對(duì)象 和 一些資料

iOS中有2套API來訪問和使用RunLoop

Foundation :NSRunLoop (是Foundation框架下的,是OC)

Core Foundation : CFRunLoopRef(Core Foundation框架下的,是C語言。C語言的類,以CF開頭,Ref結(jié)尾)

NSRunLoop和CFRunLoopRef都代表著RunLoop對(duì)象

Foundation里面是 NSRunLoop; Core Foundation里面是 CFRunLoopRef。 NSRunLoop和CFRunLoopRef都代表著RunLoop對(duì)象。 NSRunLoop是基于CFRunLoopRef的一層OC包裝,所以要了解RunLoop內(nèi)部結(jié)構(gòu),需要多研究CFRunLoopRef層面的API(Core Foundation層面)。

蘋果官方文檔

https://developer.apple.com/library/mac/documentation/Cocoa/Conceptual/Multithreading/RunLoopManagement/RunLoopManagement.html

CFRunLoopRef是開源的

http://opensource.apple.com/source/CF/CF-1151.16/

RunLoop相關(guān)類

Core Foundation中關(guān)于RunLoop的5個(gè)類

CFRunLoopRef

CFRunLoopModeRef

CFRunLoopSourceRef

CFRunLoopTimerRef

CFRunLoopObserverRef

Core Foundation中關(guān)于RunLoop的5個(gè)類

1:CFRunLoopModeRef: CFRunLoopModeRef代表RunLoop的運(yùn)行模式

一個(gè) RunLoop 包含若干個(gè) Mode,每個(gè)Mode又包含若干個(gè)Source/Timer/Observer

每次RunLoop啟動(dòng)時(shí),只能指定其中一個(gè) Mode,這個(gè)Mode被稱作 CurrentMode

如果需要切換Mode,只能退出Loop,再重新指定一個(gè)Mode進(jìn)入

這樣做主要是為了分隔開不同組的Source/Timer/Observer,讓其互不影響

系統(tǒng)默認(rèn)注冊(cè)了5個(gè)Mode:

kCFRunLoopDefaultMode:App的默認(rèn)Mode,通常主線程是在這個(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。

2:CFRunLoopSourceRef: CFRunLoopSourceRef是事件源(輸入源) 以前的分法,按照官方文檔,Source的分類

Port-Based Sources:基于端口的,跟其他線程可以交互的

Custom Input Sources:自定義輸入源

Cocoa Perform Selector Sources:我們的一些performSelector方法就是在這個(gè)里面的

現(xiàn)在的分法,按照函數(shù)的調(diào)用棧,Source的分類

Source0:非基于Port的;

Source1:基于Port的 ,通過內(nèi)核和其他線程通信、接收、分發(fā)系統(tǒng)事件。

函數(shù)調(diào)用棧,可以看到程序的執(zhí)行順序,打斷點(diǎn)即可看到,示例如下

函數(shù)調(diào)用棧,可以看到程序的執(zhí)行順序

3:CFRunLoopTimerRef: CFRunLoopTimerRef是基于時(shí)間的觸發(fā)器 基本上說的就是NSTimer

4:CFRunLoopObserverRef: CFRunLoopObserverRef是觀察者,能夠監(jiān)聽RunLoop的狀態(tài)改變。

可以監(jiān)聽的時(shí)間點(diǎn)有以下幾個(gè) /?Run Loop Observer Activities?/?

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 //128

kCFRunLoopAllActivities = 0x0FFFFFFFU };

RunLoop是有時(shí)間限制的,超過時(shí)間,就會(huì)退出 把程序殺死,RunLoop就會(huì)退出


RunLoop處理邏輯-官方版

RunLoop處理邏輯-官方版

RunLoop的事件隊(duì)列 每次運(yùn)行runLoop,線程的runLoop對(duì)自動(dòng)處理處理之前未處理的消息,并通知相關(guān)觀察者,具體順序如下:

1:通知觀察者runLoop已經(jīng)啟動(dòng),

2:通知觀察者任何即將開始的定時(shí)器,

3:通知觀察者任何即將啟動(dòng)的非基于端口的源,

4:?jiǎn)?dòng)任何準(zhǔn)備好的非基于端口的源,

5:如果基于端口的源準(zhǔn)備好并處于等待狀態(tài),立即啟動(dòng),并進(jìn)入步驟9,

6:通知觀察者線程進(jìn)入休眠,

7:將線程置于休眠直到任一下面的事件發(fā)生:

???? 1)某一事件到達(dá)基于端口的源頭

?? ? 2)定時(shí)器啟動(dòng)

???? 3)RunLoop設(shè)置的時(shí)間已經(jīng)超時(shí)

??? 4) RunLoop被顯式喚醒

8:通知觀察者線程將被喚醒

9:處理未處理的事件

???? 1)如果用戶定義的定時(shí)器啟動(dòng),處理定時(shí)器事件并重啟RunLoop,進(jìn)入步驟2

??? 2)如果輸入源啟動(dòng),傳遞相應(yīng)的消息

??? 3)如果RunLoop被顯式喚醒而且時(shí)間還沒超時(shí),重啟RunLoop,進(jìn)入步驟2

10:通知觀察者RunLoop結(jié)束


RunLoop處理邏輯-網(wǎng)友整理版

RunLoop處理邏輯-網(wǎng)友整理版


RunLoop應(yīng)用

1:NSTimer

2: ImageView顯示

3:PerformSelector

4:常駐線程

5:自動(dòng)釋放池

RunLoop應(yīng)用的demo

https://github.com/WoNiu361/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)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

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

  • ======================= 前言 RunLoop 是 iOS 和 OSX 開發(fā)中非?;A(chǔ)的一個(gè)...
    i憬銘閱讀 1,000評(píng)論 0 4
  • 轉(zhuǎn)自bireme,原地址:https://blog.ibireme.com/2015/05/18/runloop/...
    乜_啊_閱讀 1,689評(píng)論 0 5
  • Runloop是iOS和OSX開發(fā)中非?;A(chǔ)的一個(gè)概念,從概念開始學(xué)習(xí)。 RunLoop的概念 -般說,一個(gè)線程一...
    小貓仔閱讀 1,124評(píng)論 0 1
  • RunLoop 的概念 一般來講,一個(gè)線程一次只能執(zhí)行一個(gè)任務(wù),執(zhí)行完成后線程就會(huì)退出。如果我們需要一個(gè)機(jī)制,讓線...
    Mirsiter_魏閱讀 679評(píng)論 0 2
  • 如果沒有RunLoop main函數(shù)中的RunLoop 第14行代碼的UIApplicationMain函數(shù)內(nèi)部就...
    JonesCxy閱讀 679評(píng)論 0 4

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