深入淺出 RunLoop(二):數(shù)據(jù)結(jié)構(gòu)

RunLoop 系列文章

深入淺出 RunLoop(一):初識
深入淺出 RunLoop(二):數(shù)據(jù)結(jié)構(gòu)
深入淺出 RunLoop(三):事件循環(huán)機(jī)制
深入淺出 RunLoop(四):RunLoop 與線程
深入淺出 RunLoop(五):RunLoop 與 NSTimer
iOS - 聊聊 autorelease 和 @autoreleasepool:RunLoop 與 @autoreleasepool

網(wǎng)絡(luò)配圖.jpg

目錄

  • CFRunLoopRef
  • CFRunLoopModeRef
    RunLoop 的常見模式
    CFRunLoopModeRef 這樣設(shè)計有什么好處畜普?Runloop為什么會有多個 Mode游昼?
  • CFRunLoopSourceRef
  • CFRunLoopTimerRef
  • CFRunLoopObserverRef

CFRunLoopRef

RunLoop對象的底層就是一個CFRunLoopRef結(jié)構(gòu)體矢棚,它里面存儲著:

  • _pthread:RunLoop與線程是一一對應(yīng)關(guān)系
  • _commonModes:存儲著 NSString 對象的集合(Mode 的名稱)
  • _commonModeItems:存儲著被標(biāo)記為通用模式的Source0/Source1/Timer/Observer
  • _currentMode:RunLoop當(dāng)前的運行模式
  • _modes:存儲著RunLoop所有的 Mode(CFRunLoopModeRef)模式
// CFRunLoop.h
typedef struct __CFRunLoop * CFRunLoopRef;
// CFRunLoop.c
struct __CFRunLoop {
    pthread_t _pthread;  // 與線程一一對應(yīng)
    CFMutableSetRef _commonModes;
    CFMutableSetRef _commonModeItems;
    CFRunLoopModeRef _currentMode;
    CFMutableSetRef _modes;
    ...
};

CFRunLoopModeRef

  • CFRunLoopModeRef代表RunLoop的運行模式;
  • 一個RunLoop包含若干個 Mode,每個 Mode 又包含若干個Source0/Source1/Timer/Observer雀彼;
  • RunLoop啟動時只能選擇其中一個 Mode县踢,作為 currentMode;
  • 如果需要切換 Mode悼瓮,只能退出當(dāng)前 Loop戈毒,再重新選擇一個 Mode 進(jìn)入,切換模式不會導(dǎo)致程序退出横堡;
  • 不同 Mode 中的Source0/Source1/Timer/Observer能分隔開來埋市,互不影響;
  • 如果 Mode 里沒有任何Source0/Source1/Timer/Observer命贴,RunLoop會立馬退出道宅。
// 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
    ...
};

RunLoop 的常見模式

ModeName 描述
NSDefaultRunLoopMode / KCFRunLoopDefaultMode 默認(rèn)模式
UITrackingRunLoopMode 界面追蹤模式胸蛛,用于 ScrollView 追蹤觸摸滑動污茵,保證界面滑動時不受其他 Mode 影響;
NSRunLoopCommonModes / KCFRunLoopCommonModes 通用模式(默認(rèn)包含 KCFRunLoopDefaultMode 和 UITrackingRunLoopMode)

該模式不是實際存在的一種模式葬项,它只是一個特殊的標(biāo)記省咨,是同步Source0/Source1/Timer/Observer到多個 Mode 中的技術(shù)方案。被標(biāo)記為通用模式的Source0/Source1/Timer/Observer都會存放到 _commonModeItems 集合中玷室,會同步這些Source0/Source1/Timer/Observer到多個 Mode 中零蓉。

備注:

  • NSDefaultRunLoopModeNSRunLoopCommonModes屬于Foundation框架;
  • KCFRunLoopDefaultModeKCFRunLoopCommonModes屬于Core Foundation框架穷缤;
  • 前者是對后者的封裝敌蜂,作用相同。

CFRunLoopModeRef 這樣設(shè)計有什么好處津肛?Runloop為什么會有多個 Mode章喉?

  • Mode 做到了屏蔽的效果,當(dāng)RunLoop運行在 Mode1 下面的時候身坐,是處理不了 Mode2 的事件的秸脱;
  • 比如NSDefaultRunLoopMode默認(rèn)模式和UITrackingRunLoopMode滾動模式,滾動屏幕的時候就會切換到滾動模式部蛇,就不用去處理默認(rèn)模式下的事件了摊唇,保證了 UITableView 等的滾動順暢。

CFRunLoopSourceRef

  • RunLoop中有兩個很重要的概念涯鲁,一個是上面提到的模式巷查,還有一個就是事件源有序。事件源分為輸入源(Input Sources)定時器源(Timer Sources)兩種;
  • 輸入源(Input Sources)又分為Source0Source1兩種岛请,以下__CFRunLoopSource中的共用體union中的version0version1就分別對應(yīng)Source0Source1旭寿。
// CFRunLoop.h
typedef struct __CFRunLoopSource * CFRunLoopSourceRef;
// CFRunLoop.m
struct __CFRunLoopSource {
    CFRuntimeBase _base;
    uint32_t _bits;
    pthread_mutex_t _lock;
    CFIndex _order;                         /* immutable */
    CFMutableBagRef _runLoops;
    union {
        CFRunLoopSourceContext version0;    /* immutable, except invalidation */
        CFRunLoopSourceContext1 version1;   /* immutable, except invalidation */
    } _context;
};

Source0 和 Source1 的區(qū)別:

Input Sources 區(qū)別
Source0 需要手動喚醒線程:添加Source0RunLoop并不會主動喚醒線程,需要手動喚醒)
① 觸摸事件處理
performSelector:onThread:
Source1 具備喚醒線程的能力
① 基于 Port 的線程間通信
② 系統(tǒng)事件捕捉:系統(tǒng)事件捕捉是由Source1來處理崇败,然后再交給Source0處理

CFRunLoopTimerRef

  • CFRunloopTimerNSTimer是 toll-free bridged 的盅称,可以相互轉(zhuǎn)換;
  • performSelector:withObject:afterDelay:方法會創(chuàng)建timer并添加到RunLoop中后室。
// CFRunLoop.h
typedef struct CF_BRIDGED_MUTABLE_TYPE(NSTimer) __CFRunLoopTimer * CFRunLoopTimerRef;
// CFRunLoop.c
struct __CFRunLoopTimer {
    CFRuntimeBase _base;
    uint16_t _bits;
    pthread_mutex_t _lock;
    CFRunLoopRef _runLoop;           // 添加該 timer 的 RunLoop
    CFMutableSetRef _rlModes;        // 所有包含該 timer 的 modeName
    CFAbsoluteTime _nextFireDate;
    CFTimeInterval _interval;        /* immutable 理想時間間隔 */    
    CFTimeInterval _tolerance;       /* mutable 時間偏差 */  
    uint64_t _fireTSR;               /* TSR units */
    CFIndex _order;                  /* immutable */
    CFRunLoopTimerCallBack _callout; /* immutable 回調(diào)入口 */
    CFRunLoopTimerContext _context;  /* immutable, except invalidation */
};

CFRunLoopObserverRef

作用

  • CFRunLoopObserverRef用來監(jiān)聽RunLoop的 6 種活動狀態(tài)
/* 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)
};
  • UI 刷新(BeforeWaiting)
  • Autorelease pool(BeforeWaiting)

定義

// CFRunLoop.h
typedef struct __CFRunLoopObserver * CFRunLoopObserverRef;
// CFRunLoop.c
struct __CFRunLoopObserver {
    CFRuntimeBase _base;
    pthread_mutex_t _lock;
    CFRunLoopRef _runLoop;              // 添加該 observer 的 RunLoop
    CFIndex _rlCount;
    CFOptionFlags _activities;          /* immutable 監(jiān)聽的活動狀態(tài) */
    CFIndex _order;                     /* immutable */
    CFRunLoopObserverCallBack _callout; /* immutable 回調(diào)入口 */
    CFRunLoopObserverContext _context;  /* immutable, except invalidation */
};

CFRunLoopObserverRef中的_activities用來保存RunLoop的活動狀態(tài)缩膝。當(dāng)RunLoop的狀態(tài)發(fā)生改變時,通過回調(diào)_callout通知所有監(jiān)聽這個狀態(tài)的Observer咧擂。

下一篇

深入淺出 RunLoop(三):事件循環(huán)機(jī)制

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市檀蹋,隨后出現(xiàn)的幾起案子松申,更是在濱河造成了極大的恐慌,老刑警劉巖俯逾,帶你破解...
    沈念sama閱讀 206,839評論 6 482
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件贸桶,死亡現(xiàn)場離奇詭異,居然都是意外死亡桌肴,警方通過查閱死者的電腦和手機(jī)皇筛,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,543評論 2 382
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來坠七,“玉大人水醋,你說我怎么就攤上這事”胫茫” “怎么了拄踪?”我有些...
    開封第一講書人閱讀 153,116評論 0 344
  • 文/不壞的土叔 我叫張陵,是天一觀的道長拳魁。 經(jīng)常有香客問我惶桐,道長,這世上最難降的妖魔是什么潘懊? 我笑而不...
    開封第一講書人閱讀 55,371評論 1 279
  • 正文 為了忘掉前任姚糊,我火速辦了婚禮,結(jié)果婚禮上授舟,老公的妹妹穿的比我還像新娘救恨。我一直安慰自己,他們只是感情好释树,可當(dāng)我...
    茶點故事閱讀 64,384評論 5 374
  • 文/花漫 我一把揭開白布忿薇。 她就那樣靜靜地躺著裙椭,像睡著了一般。 火紅的嫁衣襯著肌膚如雪署浩。 梳的紋絲不亂的頭發(fā)上揉燃,一...
    開封第一講書人閱讀 49,111評論 1 285
  • 那天,我揣著相機(jī)與錄音筋栋,去河邊找鬼炊汤。 笑死,一個胖子當(dāng)著我的面吹牛弊攘,可吹牛的內(nèi)容都是我干的抢腐。 我是一名探鬼主播,決...
    沈念sama閱讀 38,416評論 3 400
  • 文/蒼蘭香墨 我猛地睜開眼襟交,長吁一口氣:“原來是場噩夢啊……” “哼迈倍!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起捣域,我...
    開封第一講書人閱讀 37,053評論 0 259
  • 序言:老撾萬榮一對情侶失蹤啼染,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后焕梅,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體迹鹅,經(jīng)...
    沈念sama閱讀 43,558評論 1 300
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,007評論 2 325
  • 正文 我和宋清朗相戀三年贞言,在試婚紗的時候發(fā)現(xiàn)自己被綠了斜棚。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 38,117評論 1 334
  • 序言:一個原本活蹦亂跳的男人離奇死亡该窗,死狀恐怖弟蚀,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情酗失,我是刑警寧澤粗梭,帶...
    沈念sama閱讀 33,756評論 4 324
  • 正文 年R本政府宣布,位于F島的核電站级零,受9級特大地震影響断医,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜奏纪,卻給世界環(huán)境...
    茶點故事閱讀 39,324評論 3 307
  • 文/蒙蒙 一鉴嗤、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧序调,春花似錦醉锅、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,315評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽垄琐。三九已至,卻和暖如春经柴,著一層夾襖步出監(jiān)牢的瞬間狸窘,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 31,539評論 1 262
  • 我被黑心中介騙來泰國打工坯认, 沒想到剛下飛機(jī)就差點兒被人妖公主榨干…… 1. 我叫王不留翻擒,地道東北人。 一個月前我還...
    沈念sama閱讀 45,578評論 2 355
  • 正文 我出身青樓牛哺,卻偏偏與公主長得像陋气,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子引润,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 42,877評論 2 345

推薦閱讀更多精彩內(nèi)容

  • 轉(zhuǎn)自bireme巩趁,原地址:https://blog.ibireme.com/2015/05/18/runloop/...
    乜_啊_閱讀 1,335評論 0 5
  • RunLoop 的概念 一般來講,一個線程一次只能執(zhí)行一個任務(wù)淳附,執(zhí)行完成后線程就會退出议慰。如果我們需要一個機(jī)制,讓線...
    Mirsiter_魏閱讀 615評論 0 2
  • https://blog.ibireme.com/2015/05/18/runloop/ RunLoop 是 iO...
    SmallDe閱讀 692評論 0 51
  • 轉(zhuǎn)自http://blog.ibireme.com/2015/05/18/runloop 深入理解RunLoop ...
    飄金閱讀 976評論 0 4
  • http://www.cocoachina.com/ios/20150601/11970.html RunLoop...
    紫色冰雨閱讀 829評論 0 3