RunLoop

簡介

什么是 RunLoop ?

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

RunLoop 的基本作用是什么:
  • 保持程序的持續(xù)運(yùn)行;
  • 處理 App 中的各種事件(比如觸摸事件、定時器事件、Selector 事件);
  • 節(jié)省 CPU 資源,提高程序性能:該做事時做事,該休息時休息;
如果沒有RunLoop
int main(int argc, char * argv[])
{
    // 程序開始
    NSLog(@"execute main function");
    // 程序結(jié)束
    return 0;
}

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

如果有了RunLoop
int main(int argc, char * argv[]) 
{
    BOOL running = YES;
    do 
        {
            // 執(zhí)行各種任務(wù),處理各種事件
           // ......
        } while (running);
    return 0;
}

有 RunLoop 的情況下:由于 main 函數(shù)里面啟動了個 RunLoop ,所以程序并不會馬上退出,保持持續(xù)運(yùn)行狀態(tài)

main函數(shù)中的RunLoop
int main(int argc, char * argv[])
{
    @autoreleasepool
    {
        return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class]));
    }
}

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

RunLoop對象

iOS 中哪些 API 來訪問和使用 RunLoop?
  • Foundation
    NSRunLoop
  • Core Foundation
    CFRunLoopRef

NSRunLoop 和 CFRunLoopRef 都代表著 RunLoop 對象;

NSRunLoop 是基于 CFRunLoopRef 的一層 OC 包裝,所以要了解RunLoop內(nèi)部結(jié)構(gòu),需要多研究CFRunLoopRef層面的API(Core Foundation層面);

RunLoop資料
RunLoop與線程
  • 每條線程都有唯一的一個與之對應(yīng)的 RunLoop 對象;
  • 主線程的 RunLoop 已經(jīng)自動創(chuàng)建好了,子線程的 RunLoop 需要主動創(chuàng)建;
  • RunLoop 在第一次獲取時創(chuàng)建,在線程結(jié)束時銷毀;
獲得 RunLoop 對象
  • Foundation
// 獲得當(dāng)前線程的RunLoop對象
[NSRunLoop currentRunLoop]; 
// 獲得主線程的RunLoop對象
[NSRunLoop mainRunLoop]; 
  • Core Foundation
// 獲得當(dāng)前線程的RunLoop對象
CFRunLoopGetCurrent(); 
 // 獲得主線程的RunLoop對象
CFRunLoopGetMain();

RunLoop相關(guān)類

Core Foundation 中有幾個關(guān)于RunLoop的類?

Core Foundation 中有5個關(guān)于RunLoop的類;

  • CFRunLoopRef
  • CFRunLoopModeRef
  • CFRunLoopSourceRef
  • CFRunLoopTimerRef
  • CFRunLoopObserverRef
RunLoop
CFRunLoopModeRef
  • CFRunLoopModeRef 代表 RunLoop 的運(yùn)行模式;
  • 一個 RunLoop 包含若干個 Mode,每個 Mode 又包含若干個Source/Observer/Timer;
  • 每次 RunLoop 啟動時,只能指定其中一個 Mode,這個 Mode 被稱作 CurrentMode;
  • 如果需要切換 Mode,只能退出 Loop,再重新指定一個 Mode 進(jìn)入
  • 這樣做主要是為了分隔開不同組的 Source/Observer/Timer,讓其互不影響;
RunLoop 中有幾種 Mode?

系統(tǒng)默認(rèn)注冊了 5 種 Mode;

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

CFRunLoopSourceRef 是事件源(輸入源)

  • 按照 Apple 官方文檔 Sources 的分類:
    Port-Based Sources
    Custom Input Sources
    Cocoa Perform Selector Sources

  • 按照函數(shù)調(diào)用棧 Sources 的分類:
    Source0:非基于 Port;
    Source1:基于 Port,通過內(nèi)核和其他線程通信,接受,分發(fā)系統(tǒng)事件;

CFRunLoopTimerRef

CFRunLoopTimerRef 是基于時間的觸發(fā)器;
基本上說的就是 NSTimer;

CFRunLoopObserverRef

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

可以監(jiān)聽的時間點(diǎn)有以下幾個

typedef CF_OPTIONS(CFOptionFlags, CFRunLoopActivity) 
{
    // 即將進(jìn)入 RunLoop
    kCFRunLoopEntry = (1UL << 0) = 1,
    // 即將處理 Timer
    kCFRunLoopBeforeTimers = (1UL << 1) = 2,
    // 即將處理 Source
    kCFRunLoopBeforeSources = (1UL << 2) = 4,
    // 即將進(jìn)入 睡眠
    kCFRunLoopBeforeWaiting = (1UL << 5) = 32,
    // 剛從 睡眠 中 喚醒
    kCFRunLoopAfterWaiting = (1UL << 6) = 64,
    // 即將退出 RunLoop
    kCFRunLoopExit = (1UL << 7) = 128,
    // 所有活動
    kCFRunLoopAllActivities = 0x0FFFFFFFU
};

RunLoop 處理邏輯

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

RunLoop 應(yīng)用

  • NSTimer
  • ImageView顯示
  • PerformSelector
  • 常駐線程
  • 自動釋放池
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

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

  • 如果沒有RunLoop main函數(shù)中的RunLoop 第14行代碼的UIApplicationMain函數(shù)內(nèi)部就...
    JonesCxy閱讀 665評論 0 4
  • RunLoop 文章目錄 RunLoop簡介 1.1 什么是RunLoop? 1.2 RunLoop和線程 1.3...
    May_d8f1閱讀 345評論 0 1
  • 1 RunLoop簡介 神秘的RunLoop。一個應(yīng)用開始運(yùn)行以后放在那里,如果不對它進(jìn)行任何操作,這個應(yīng)用就像靜...
    Claire_wu閱讀 1,876評論 3 30
  • 本文首發(fā)于我的個人博客:「程序員充電站」[https://itcharge.cn]文章鏈接:「傳送門」[https...
    ITCharge閱讀 61,856評論 50 541
  • 文章目錄RunLoop簡介1.1 什么是RunLoop? 1.2 RunLoop和線程1.3 默認(rèn)情況下主線程的R...
    lusen_b閱讀 457評論 0 2

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