淺談iOS中RunLoop的使用及原理

什么是RunLoop

從字面意思看

運(yùn)行循環(huán)
Paste_Image.png

跑圈

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


int main(int argc, char * argv[]) {
    NSLog(@"execute main function");
    return 0;
}
  • 沒(méi)有RunLoop的情況下
  • 第3行后程序就結(jié)束了
如果有了RunLoop

int main(int argc, char * argv[]) {
    BOOL running = YES;
    do {
        // 執(zhí)行各種任務(wù),處理各種事件
             // ......
    } while (running);
    return 0;
}
  • 有RunLoop的情況下
  • 由于main函數(shù)里面啟動(dòng)了個(gè)RunLoop,所以程序并不會(huì)馬上退出,保持持續(xù)運(yùn)行狀態(tài)
main函數(shù)中的RunLoop
int main(int argc, char * argv[]) {
    @autoreleasepool {
        return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class]));
    }
}
  • UIApplicationMain函數(shù)內(nèi)部就啟動(dòng)了一個(gè)RunLoop
  • 所以UIApplicationMain函數(shù)一直沒(méi)有返回,保持了程序的持續(xù)運(yùn)行
  • 這個(gè)默認(rèn)啟動(dòng)的RunLoop是跟主線程相關(guān)聯(lián)的

RunLoop對(duì)象

  • iOS中有2套API來(lái)訪問(wèn)和使用RunLoop

  • 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是開(kāi)源的

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

RunLoop與線程
  • 每條線程都有唯一的一個(gè)與之對(duì)應(yīng)的RunLoop對(duì)象

  • 主線程的RunLoop已經(jīng)自動(dòng)創(chuàng)建好了,子線程的RunLoop需要主動(dòng)創(chuàng)建

  • RunLoop在第一次獲取時(shí)創(chuàng)建,在線程結(jié)束時(shí)銷毀

獲得RunLoop對(duì)象
Foundation

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

Core Foundation

CFRunLoopGetCurrent(); // 獲得當(dāng)前線程的RunLoop對(duì)象
CFRunLoopGetMain(); // 獲得主線程的RunLoop對(duì)象
RunLoop相關(guān)類
  • Core Foundation中關(guān)于RunLoop的5個(gè)類
  • CFRunLoopRef
  • CFRunLoopModeRef
  • CFRunLoopSourceRef
  • CFRunLoopTimerRef
  • CFRunLoopObserverRef
Paste_Image.png
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)入

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

CFRunLoopModeRef
  • 系統(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

CFRunLoopSourceRef
  • CFRunLoopSourceRef是事件源(輸入源)
    以前的分法
  • Port-Based Sources
  • Custom Input Sources
  • Cocoa Perform Selector Sources
    現(xiàn)在的分法
  • Source0:非基于Port的
  • Source1:基于Port的
CFRunLoopTimerRef
  • CFRunLoopTimerRef是基于時(shí)間的觸發(fā)器

  • 基本上說(shuō)的就是NSTimer

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

  • 可以監(jiān)聽(tīng)的時(shí)間點(diǎn)有以下幾個(gè)

Paste_Image.png

RunLoop處理邏輯-官方版

Paste_Image.png
Paste_Image.png

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

Paste_Image.png
最后編輯于
?著作權(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)容

  • 一、什么是runloop 字面意思是“消息循環(huán)、運(yùn)行循環(huán)”。它不是線程,但它和線程息息相關(guān)。一般來(lái)講,一個(gè)線程一次...
    WeiHing閱讀 8,305評(píng)論 11 111
  • Run loop 剖析:Runloop 接收的輸入事件來(lái)自兩種不同的源:輸入源(intput source)和定時(shí)...
    Mitchell閱讀 12,640評(píng)論 17 111
  • 如果沒(méi)有RunLoop main函數(shù)中的RunLoop 第14行代碼的UIApplicationMain函數(shù)內(nèi)部就...
    JonesCxy閱讀 665評(píng)論 0 4
  • 1 RunLoop簡(jiǎn)介 神秘的RunLoop。一個(gè)應(yīng)用開(kāi)始運(yùn)行以后放在那里,如果不對(duì)它進(jìn)行任何操作,這個(gè)應(yīng)用就像靜...
    Claire_wu閱讀 1,877評(píng)論 3 30
  • 本文首發(fā)于我的個(gè)人博客:「程序員充電站」[https://itcharge.cn]文章鏈接:「?jìng)魉烷T」[https...
    ITCharge閱讀 61,859評(píng)論 50 541

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