runLoop

這篇文章主要總結(jié)下runloop的主要組成及實現(xiàn)流程,以及衍生出來的一些相關(guān)問題:
1.組成
2.主要方法(實現(xiàn)流程)
3.線程保活需要添加item
4.GCD和NSTimer的準(zhǔn)確性

1.組成

CFRunLoop類,
CFRunLoopMode類,
CFRunLoopSource類,
CFRunLoopTimer類,
CFRunLoopObserver類

//一個runloop中包含
struct __CFRunLoop {
    pthread_t _pthread;                     //對應(yīng)的線程,runloop和線程是一一對應(yīng)的
    CFMutableSetRef _commonModes;           //commonMode是針對kCFRunLoopCommonModes,是_modes的子集
    CFMutableSetRef _commonModeItems;
    CFRunLoopModeRef _currentMode;          //當(dāng)前的mode
    CFMutableSetRef _modes;                 //runloop中所有的mode
};

//mode
struct __CFRunLoopMode {
    CFMutableSetRef _sources0;      //系統(tǒng)事件
    CFMutableSetRef _sources1;      //線程通信
    CFMutableArrayRef _observers;   //監(jiān)聽者
    CFMutableArrayRef _timers;      //定時器
};

mode類型有

    UITrackingRunLoopMode           //處理滾動
    kCFRunLoopDefaultMode           //默認(rèn)模式
    UIInitializationRunLoopMode     //啟動程序后的過渡mode,啟動完成后就不再使用
    GSEventReceiveRunLoopMode       //Graphic相關(guān)事件的mode,通常用不到
    kCFRunLoopCommonModes           //監(jiān)聽commonModes中mode,比如mainRunloop中commonModes包含UITrackingRunLoopMode,kCFRunLoopDefaultMode,所以timer設(shè)置mode = kCFRunLoopCommonModes,就可以同時監(jiān)聽這兩種mode下的活動

2.實現(xiàn)流程

其中runloop主要方法是

SInt32 CFRunLoopRunSpecific(CFRunLoopRef rl, CFStringRef modeName, CFTimeInterval seconds, Boolean returnAfterSourceHandled) {
    
    //判斷mode是否存在,mode中是否有需要執(zhí)行的東西,通過這里可以看出如果需要讓一個線程?;?這里需要開啟runloop之外,還需要有mode和任務(wù)(source,timer,observer...)
    if (NULL == currentMode || __CFRunLoopModeIsEmpty(rl, currentMode, rl->_currentMode)) {
        Boolean did = false;
        if (currentMode) __CFRunLoopModeUnlock(currentMode);
        __CFRunLoopUnlock(rl);
        return did ? kCFRunLoopRunHandledSource : kCFRunLoopRunFinished;
    }
    
    //通知監(jiān)聽者即將進(jìn)入runloop
    __CFRunLoopDoObservers(rl, currentMode, kCFRunLoopEntry);
    
    //執(zhí)行runloop
    result = __CFRunLoopRun(rl, currentMode, seconds, returnAfterSourceHandled, previousMode);
    
    //通知監(jiān)聽者已經(jīng)退出runloop
    __CFRunLoopDoObservers(rl, currentMode, kCFRunLoopExit);

    return result;
}

//就是一個do-while循環(huán)
static int32_t __CFRunLoopRun(CFRunLoopRef rl, CFRunLoopModeRef rlm, CFTimeInterval seconds, Boolean stopAfterHandle, CFRunLoopModeRef previousMode) {
    
    int32_t retVal = 0;
    do {
        02、通知Observers:即將處理Timers
        03、通知Observers:即將處理Sources
        04、處理Blocks
        05、處理Source0(可能會再次處理Blocks)
        06、如果存在Source1,就跳轉(zhuǎn)到第8步
        07、通知Observers:開始休眠(等待消息喚醒)

            ...(休眠)

        08、通知Observers:結(jié)束休眠(被某個消息喚醒)
        01> 處理Timer
        02> 處理GCD Async To Main Queue
        03> 處理Source1
        09、處理Blocks
        10、根據(jù)前面的執(zhí)行結(jié)果,決定如何操作
        retVal = ...(來決定是否退出循環(huán))
    } while (0 == retVal);

    return retVal;
}

這個方法run函數(shù)中,最終用來執(zhí)行這些source,timer..的就是下面圖中,右邊黑框中的函數(shù)


WechatIMG19.jpeg

其實我們的函數(shù)調(diào)用大部分都是始于runLoop,比如ViewController中的viewDidLoad,這些方法(方法鏈,我指的是整個函數(shù)調(diào)用棧,什么時候開始的第一個函數(shù)調(diào)用)什么時候調(diào)用,都是runloop來控制的,我們在viewDidLoad中打斷點發(fā)現(xiàn)


WechatIMG18.jpeg

3.線程?;?/h1>
-(void)threadAlive {
    NSThread *thread = [[NSThread alloc] initWithBlock:^{
        [[NSRunLoop currentRunLoop] addPort:[[NSPort alloc] init] forMode:NSDefaultRunLoopMode];
        while (1) {
            [[NSRunLoop currentRunLoop] runMode:NSDefaultRunLoopMode beforeDate:[NSDate distantFuture]];
        }
    }];
    [thread start];
}
  • [[NSRunLoop currentRunLoop] run] 是無法停止的,所以如果不是整個app都需要保活的話要使用上述方案;
  • 需要添加任務(wù)到mode中,否則無法開啟runloop循環(huán), 上述CFRunLoopRunSpecific函數(shù)中有明確的代碼;

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

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

  • runloop 的狀態(tài)待完善 相關(guān)面試題 講講 RunLoop,項目中有用到嗎?1、控制線程的生命周期(線程?;?...
    張_何閱讀 301評論 0 0
  • 前言 對iOS開發(fā)者而言,runloop是一個老生常談的話題,但凡是iOS開發(fā)者,在工作中必然直接或間接的接觸過r...
    VV木公子閱讀 3,169評論 4 21
  • 一、什么是RunLoop 1、概念:運(yùn)行循環(huán),在程序運(yùn)行過程中,循環(huán)的做一些事,實質(zhì)就是一個do while()循...
    王的for閱讀 642評論 0 1
  • 1 Runloop機(jī)制原理 深入理解RunLoop http://www.cocoachina.com/ios/2...
    Kevin_Junbaozi閱讀 4,239評論 4 30
  • 關(guān)于 runloop 面試中經(jīng)常被問到: 講講 RunLoop,項目中有用到嗎? RunLoop內(nèi)部實現(xiàn)邏輯? R...
    齊玉婷閱讀 326評論 0 1

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