RunLoop部分

--------------------RunLoop--------------------

什么是RunLoop

運(yùn)行循環(huán),在程序運(yùn)行過(guò)程中循環(huán)做一些事情

RunLoopde 應(yīng)用范疇

定時(shí)器(Timer)、PerformSelector
GCD Async Main Queue
事件響應(yīng)、手勢(shì)識(shí)別、界面刷新
網(wǎng)絡(luò)請(qǐng)求
AutoreleasePool

RunLoop與線程

  1. 每條線程都有唯一的一個(gè)與之對(duì)應(yīng)的RunLoop對(duì)象
  2. RunLoop保存在一個(gè)全局的Dictionary里,線程作為key,RunLoop作為value
  3. 線程剛創(chuàng)建時(shí)并沒(méi)有RunLoop對(duì)象,RunLoop會(huì)在第一次獲取它時(shí)創(chuàng)建
  4. RunLoop會(huì)在線程結(jié)束時(shí)銷毀
  5. 主線程的RunLoop已經(jīng)自動(dòng)獲?。▌?chuàng)建),子線程默認(rèn)沒(méi)有開(kāi)啟RunLoop

獲得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)的5個(gè)類:
CFRunLoopRef
CFRunLoopModeRef
CFRunLoopSourceRef
CFRunLoopTimerRef
CFRunLoopObserverRef

CFRunLoop和 CFRunLoopMode

// CFRunLoop.h
typedef struct __CFRunLoop * CFRunLoopRef;
// CFRunLoop.c
struct __CFRunLoop {
    pthread_t _pthread;  // 與線程一一對(duì)應(yīng)
    CFMutableSetRef _commonModes;
    CFMutableSetRef _commonModeItems;
    CFRunLoopModeRef _currentMode;
    CFMutableSetRef _modes;
    ...
};
// CFRunLoop.h
typedef struct __CFRunLoopMode *CFRunLoopModeRef;
// CFRunLoop.c
struct __CFRunLoopMode {
    CFStringRef _name;             // mode 類型,如:NSDefaultRunLoopMode
    CFMutableSetRef _sources0;     // CFRunLoopSourceRef
    CFMutableSetRef _sources1;     // CFRunLoopSourceRef
    CFMutableArrayRef _observers;  // CFRunLoopObserverRef
    CFMutableArrayRef _timers;     // CFRunLoopTimerRef
    ...
};

CFRunLoopModeRef

  • CFRunLoopModeRef代表RunLoop的運(yùn)行模式
  • 一個(gè)RunLoop包含若干個(gè)Mode,每個(gè)Mode又包含若干個(gè)Source0/Source1/Timer/Observer
  • RunLoop啟動(dòng)時(shí)只能選擇其中一個(gè)Mode,作為currentMode
  • 如果需要切換Mode,只能退出當(dāng)前Loop,再重新選擇一個(gè)Mode進(jìn)入
    不同組的Source0/Source1/Timer/Observer能分隔開(kāi)來(lái),互不影響
  • 如果Mode里沒(méi)有任何Source0/Source1/Timer/Observer,RunLoop會(huì)立馬退出

常見(jiàn)的兩種mode:

  • kCFRunLoopDefaultMode(NSDefaultRunLoopMode):App的默認(rèn)Mode,通常主線程是在這個(gè)Mode下運(yùn)行
  • UITrackingRunLoopMode:界面跟蹤 Mode,用于 ScrollView 追蹤觸摸滑動(dòng),保證界面滑動(dòng)時(shí)不受其他 Mode 影響

CFRunLoopObserverRef

/* Run Loop Observer Activities */
typedef CF_OPTIONS(CFOptionFlags, CFRunLoopActivity) {
    kCFRunLoopEntry = (1UL << 0),          // 即將進(jìn)入 RunLoop
    kCFRunLoopBeforeTimers = (1UL << 1),   // 即將處理 Timers
    kCFRunLoopBeforeSources = (1UL << 2),  // 即將處理 Sources
    kCFRunLoopBeforeWaiting = (1UL << 5),  // 即將進(jìn)入休眠
    kCFRunLoopAfterWaiting = (1UL << 6),   // 剛從休眠中喚醒
    kCFRunLoopExit = (1UL << 7),           // 即將退出 RunLoop
    kCFRunLoopAllActivities = 0x0FFFFFFFU  // 表示以上所有狀態(tài)
};

添加RunLoop的監(jiān)聽(tīng):

// 創(chuàng)建Observer
CFRunLoopObserverRef observer = CFRunLoopObserverCreateWithHandler(kCFAllocatorDefault, kCFRunLoopAllActivities, YES, 0, ^(CFRunLoopObserverRef observer, CFRunLoopActivity activity) {
    switch (activity) {
        case kCFRunLoopEntry: {
            NSLog(@"kCFRunLoopEntry");
            break;
        }
        case kCFRunLoopBeforeTimers: {
            NSLog(@"kCFRunLoopEntry");
        } break;
        case kCFRunLoopBeforeSources: {
            NSLog(@"kCFRunLoopEntry");
        } break;
        case kCFRunLoopBeforeWaiting: {
            NSLog(@"kCFRunLoopEntry");
        } break;
        case kCFRunLoopAfterWaiting: {
            NSLog(@"kCFRunLoopEntry");
        } break;
        case kCFRunLoopExit: {
            NSLog(@"kCFRunLoopExit");
            break;
        }
        default:
            break;
    }
});
// 添加Observer到RunLoop中
CFRunLoopAddObserver(CFRunLoopGetCurrent(), observer, kCFRunLoopCommonModes);
// 釋放
CFRelease(observer);

RunLoop的運(yùn)行邏輯

先上一張老圖


image.png
  • Source0
    觸摸事件處理
    performSelector:onThread:

  • Source1
    基于Port的線程間通信
    系統(tǒng)事件捕捉

  • Timers
    NSTimer
    performSelector:withObject:afterDelay:

  • Observers
    用于監(jiān)聽(tīng)RunLoop的狀態(tài)
    UI刷新(BeforeWaiting)
    Autorelease pool(BeforeWaiting)

過(guò)程:


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

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

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