RunLoop

一、獲取RunLoop

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

Core Foundation
CFRunLoopGetCurrent(); // 獲得當(dāng)前線程的RunLoop對(duì)象
CFRunLoopGetMain(); // 獲得主線程的RunLoop對(duì)象

二、RunLoop與線程關(guān)系
1、每條線程都有唯一的一個(gè)與之對(duì)應(yīng)的RunLoop對(duì)象
2、RunLoop保存在一個(gè)全局的Dictionary里,線程作為key,RunLoop作為value
3、主線程的RunLoopmain函數(shù)中系統(tǒng)創(chuàng)建,子線程的RunLoop需要主動(dòng)創(chuàng)建
4、RunLoop在第一次獲取時(shí)創(chuàng)建,在線程結(jié)束時(shí)銷毀

三、RunLoop結(jié)構(gòu)體

struct __CFRunLoop {
    CFRuntimeBase _base;
    pthread_mutex_t _lock;          /* locked for accessing mode list */
    __CFPort _wakeUpPort;           // used for CFRunLoopWakeUp 
    Boolean _unused;
    volatile _per_run_data *_perRunData;              // reset for runs of the run loop
    pthread_t _pthread;
    uint32_t _winthread;
    CFMutableSetRef _commonModes;
    CFMutableSetRef _commonModeItems;
    CFRunLoopModeRef _currentMode;
    CFMutableSetRef _modes;
    struct _block_item *_blocks_head;
    struct _block_item *_blocks_tail;
    CFAbsoluteTime _runTime;
    CFAbsoluteTime _sleepTime;
    CFTypeRef _counterpart;
};

CFRunLoopModeRef其實(shí)是指向__CFRunLoopMode結(jié)構(gòu)體的指針,CFRunLoopModeRef代表RunLoop的運(yùn)行模式,一個(gè)RunLoop包含若干個(gè)Mode,每個(gè)Mode又包含若干個(gè)Source0/Source1/Timer/Observer,而RunLoop啟動(dòng)時(shí)只能選擇其中一個(gè)Mode作為currentMode
1、Source1: 基于Port的線程間通信,通過內(nèi)核和其他線程相互發(fā)送消息(與內(nèi)核相關(guān))
2、Source0: 非基于Port的,用于主動(dòng)觸發(fā),例如觸摸事件,PerformSelectors
3、Timers: 定時(shí)器,NSTimer
4、Observer: 監(jiān)聽器,用于監(jiān)聽RunLoop的狀態(tài)
總結(jié)
CFRunLoopModeRef代表RunLoop的運(yùn)行模式
一個(gè)RunLoop包含若干個(gè)Mode,每個(gè)Mode又包含若干個(gè)Source、Timer、Observer
每次RunLoop啟動(dòng)時(shí),只能指定其中一個(gè)Mode,這個(gè)Mode被稱作CurrentMode,如果需要切換Mode,只能退出RunLoop,再重新指定一個(gè)Mode進(jìn)入,這樣做主要是為了分隔開不同組的Source、Timer、Observer,讓其互不影響。如果Mode里沒有任何Source0/Source1/Timer/Observer,RunLoop會(huì)立馬退出。
一種Mode中可以有多個(gè)Source(事件源,輸入源,基于端口事件源例鍵盤觸摸等) Observer(觀察者,觀察當(dāng)前RunLoop運(yùn)行狀態(tài)) 和Timer(定時(shí)器事件源)。但是必須至少有一個(gè)Source或者Timer,因?yàn)槿绻?code>Mode為空,RunLoop運(yùn)行到空模式不會(huì)進(jìn)行空轉(zhuǎn),就會(huì)立刻退出。

四、RunLoop的運(yùn)行模式
RunLoop運(yùn)行模式一共五種,前兩種比較常見
1、kCFRunLoopDefaultMode:App的默認(rèn)Mode,通常主線程是在這個(gè)Mode下運(yùn)行
2、UITrackingRunLoopMode:界面跟蹤 Mode,用于 ScrollView 追蹤觸摸滑動(dòng),保證界面滑動(dòng)時(shí)不受其他 Mode 影響
3、UIInitializationRunLoopMode: 在剛啟動(dòng) App 時(shí)第進(jìn)入的第一個(gè) Mode,啟動(dòng)完成后就不再使用,會(huì)切換到kCFRunLoopDefaultMode
4、GSEventReceiveRunLoopMode: 接受系統(tǒng)事件的內(nèi)部 Mode,通常用不到
5、kCFRunLoopCommonModes: 這是一個(gè)占位用的Mode,作為標(biāo)記kCFRunLoopDefaultMode和UITrackingRunLoopMode用,并不是一種真正的Mode

五、RunLoop釋放機(jī)制
RunLoop內(nèi)部有一個(gè)自動(dòng)釋放池,當(dāng)RunLoop開啟時(shí),就會(huì)自動(dòng)創(chuàng)建一個(gè)自動(dòng)釋放池,當(dāng)RunLoop在休息之前會(huì)釋放掉自動(dòng)釋放池的東西,然后重新創(chuàng)建一個(gè)新的空的自動(dòng)釋放池,當(dāng)RunLoop被喚醒重新開始跑圈時(shí),Timer,Source等新的事件就會(huì)放到新的自動(dòng)釋放池中,當(dāng)RunLoop退出的時(shí)候也會(huì)被釋放。

最后編輯于
?著作權(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),簡書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

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

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