什么是RunLoop?

RunLoop是通過內(nèi)部維護的事件循環(huán)來對事件和消息進行管理的對象

  • 沒有消息需要處理時,Runloop將線程控制器交給系統(tǒng)牧嫉,即從用戶態(tài)->內(nèi)核態(tài),休眠以避免資源占用
  • 有消息需要被處理時竭翠,立即喚醒,又從內(nèi)核態(tài)->用戶態(tài)嘉汰。
    screenshot_2022_12_19_10_44_46.png

Runloop核心

Runloop可以簡單地理解成一個while(true)的循環(huán)皿曲,但又不是while循環(huán)這么簡單,因為這樣的實現(xiàn)會使CPU進行大量無謂的空轉(zhuǎn)粤铭。所以挖胃,Runloop機制的核心就是保證線程在有events需要處理時能喚醒,在沒有events時能進行休眠。
而實現(xiàn)真正的休眠酱鸭,是靠沒有events時從用戶態(tài)->內(nèi)核態(tài)實現(xiàn)的吗垮,當(dāng)有事件時,系統(tǒng)內(nèi)核通過mach_msg()或者mach port方法將事件發(fā)送給對應(yīng)的Runloop凹髓,Runloop收到事件后從休眠狀態(tài)切換到喚醒狀態(tài)烁登,并從內(nèi)核態(tài)->用戶態(tài)

數(shù)據(jù)結(jié)構(gòu)

NSRunLoop是CFRunLoop的封裝蔚舀,提供了面向?qū)ο蟮腁PI

  • CFRunLoop
  • CFRunLoopMode
  • Source/Timer/Observer
CFRunLoop{
pthread -----> 線程和runloop是一一對應(yīng)的
currentMode  ---> CFRunLoopMode
modes  --->  NSMutableSet<CFRunLoopMode*>
commonModes  ---> NSMutableSet<NSString*>
commonModeItems  ---> {多個Observer饵沧,Timer, Source}
}
screenshot_2023_02_10_12_21_05.png

CFRunLoopMode

CFRunLoopMode內(nèi)部數(shù)據(jù)結(jié)構(gòu)如下

CFRunLoopMode {
name (如NSDefaultRunLoopMode)
sources0  ---> NSMutableSet
sources1  ---> NSMutableSet
observers   ---> NSMutableArray
timers  ---> NSMutableArray
}

mode是管理著Runloop與source/timer/observer之間的橋梁赌躺,在一開始會注冊五個mode

  • kCFRunLoopDefaultMode: App的默認(rèn) Mode狼牺,通常主線程是在這個 Mode 下運行的。
  • UITrackingRunLoopMode: 界面跟蹤 Mode寿谴,用于 ScrollView 追蹤觸摸滑動锁右,保證界面滑動時不受其他 Mode 影響。默認(rèn)NSTimer是被加入到default mode中的讶泰,所以當(dāng)滑動時Runloop切換到tracking mode,這時default mode中的Timer回調(diào)不會被調(diào)用拂到,所以NSTimer的精度沒有CADisplayLinker高痪署。
  • UIInitializationRunLoopMode: 在剛啟動 App 時進入的第一個 Mode,啟動完成后就不再使用兄旬。
  • GSEventReceiveRunLoopMode: 接受系統(tǒng)事件的內(nèi)部 Mode狼犯,通常用不到。
  • kCFRunLoopCommonModes/NSRunLoopCommonModes:
    1.這是一個占位的 Mode领铐,不是實際存在的一種mode悯森。
    2.是同步Source/Timer/Observer到多個Mode中的一種技術(shù)方案

如果需要將事件加入到多個mode中,則將它注冊到commonMode中绪撵,該mode實際上是多個mode的集合瓢姻。
出于將source/timer/observer分隔開的目的,RunLoop一次只能運行在一個mode下音诈,當(dāng)運行時在RunLoop的currentMode屬性中會標(biāo)記當(dāng)前運行的mode幻碱。而當(dāng)要切換mode時,RunLoop必須先退出细溅,并選中一個mode重新進入褥傍,達到切換mode的目的。在切換mode時喇聊,被加入到commonModes中的事件會被拷貝一次到運行的mode中恍风。

CFRunloopObserver

觀測時間點

  • kCFRunLoopEntry 將進入runloop
  • kCFRunLoopBeforeTimers
  • kCFRunLoopBeforeSouces
  • kCFRunLoopBeforeWaiting 將要進入休眠狀態(tài)(即將從用戶態(tài)切換到內(nèi)核態(tài)
  • kCFRunLoopAfterWaiting 開始喚醒(從內(nèi)核態(tài)進入到用戶態(tài)不久
    kCFRunLoopExit runloop退出的通知

各個數(shù)據(jù)結(jié)構(gòu)之間的關(guān)系?

RunLoop和線程一一對應(yīng)--->多個mode--->{多個Source,Timer朋贬,Observer}

如何喚醒Runloop

1. CFRunLoopSource

source0: 需要手動喚醒線程

該類Source是App的內(nèi)部事件凯楔,不具有獨立喚醒Runloop的能力。一個Source0需要被處理時兄世,他需要被CFRunLoopSourceSignal()函數(shù)標(biāo)記為待處理啼辣,并調(diào)用CFRunLoopWakeUp函數(shù)來喚醒Runloop,CFRunLoopWakeUp函數(shù)內(nèi)部通過一個_wakeUpPort成員變量來喚醒Runloop御滩,推測該變量是一個mach port鸥拧,Runloop只有通過mach portmach_msg()才可以喚醒。喚醒后通過調(diào)用__CFRunLoopDoSources0函數(shù)來處理Source0事件削解,并在之后將該事件標(biāo)記為已處理富弦。

source1: 具備喚醒線程的能力

一般是由硬件生成的source,如觸摸氛驮、點擊腕柜、搖晃、旋轉(zhuǎn)等矫废。此類Source可喚醒Runloop盏缤。

2.Timer

使用NSTimer API注冊執(zhí)行的任務(wù),就屬于這一類

3. Observer

某個Observer可以監(jiān)聽runloop的狀態(tài)變化蓖扑,并作出反應(yīng)

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末唉铜,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子律杠,更是在濱河造成了極大的恐慌潭流,老刑警劉巖,帶你破解...
    沈念sama閱讀 206,378評論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件柜去,死亡現(xiàn)場離奇詭異灰嫉,居然都是意外死亡,警方通過查閱死者的電腦和手機嗓奢,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,356評論 2 382
  • 文/潘曉璐 我一進店門讼撒,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人蔓罚,你說我怎么就攤上這事椿肩。” “怎么了豺谈?”我有些...
    開封第一講書人閱讀 152,702評論 0 342
  • 文/不壞的土叔 我叫張陵郑象,是天一觀的道長。 經(jīng)常有香客問我茬末,道長厂榛,這世上最難降的妖魔是什么盖矫? 我笑而不...
    開封第一講書人閱讀 55,259評論 1 279
  • 正文 為了忘掉前任,我火速辦了婚禮击奶,結(jié)果婚禮上辈双,老公的妹妹穿的比我還像新娘。我一直安慰自己柜砾,他們只是感情好湃望,可當(dāng)我...
    茶點故事閱讀 64,263評論 5 371
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著痰驱,像睡著了一般证芭。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上担映,一...
    開封第一講書人閱讀 49,036評論 1 285
  • 那天废士,我揣著相機與錄音,去河邊找鬼蝇完。 笑死官硝,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的短蜕。 我是一名探鬼主播氢架,決...
    沈念sama閱讀 38,349評論 3 400
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼朋魔!你這毒婦竟也來了达箍?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 36,979評論 0 259
  • 序言:老撾萬榮一對情侶失蹤铺厨,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后硬纤,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體解滓,經(jīng)...
    沈念sama閱讀 43,469評論 1 300
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 35,938評論 2 323
  • 正文 我和宋清朗相戀三年筝家,在試婚紗的時候發(fā)現(xiàn)自己被綠了洼裤。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 38,059評論 1 333
  • 序言:一個原本活蹦亂跳的男人離奇死亡溪王,死狀恐怖腮鞍,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情莹菱,我是刑警寧澤移国,帶...
    沈念sama閱讀 33,703評論 4 323
  • 正文 年R本政府宣布,位于F島的核電站道伟,受9級特大地震影響迹缀,放射性物質(zhì)發(fā)生泄漏使碾。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 39,257評論 3 307
  • 文/蒙蒙 一祝懂、第九天 我趴在偏房一處隱蔽的房頂上張望票摇。 院中可真熱鬧,春花似錦砚蓬、人聲如沸矢门。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,262評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽祟剔。三九已至,卻和暖如春缕允,著一層夾襖步出監(jiān)牢的瞬間峡扩,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 31,485評論 1 262
  • 我被黑心中介騙來泰國打工障本, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留教届,地道東北人。 一個月前我還...
    沈念sama閱讀 45,501評論 2 354
  • 正文 我出身青樓驾霜,卻偏偏與公主長得像案训,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子粪糙,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 42,792評論 2 345

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