RunLoop

在我們平時的開發(fā)過程中會涉及到RunLoop的開發(fā)其實是非常少的,但是RunLoop其實是保證App能夠正常運行的一個非常關(guān)鍵的東西拓劝。

什么是RunLoop熟丸?
我們現(xiàn)在的手機系統(tǒng)都是一個事件驅(qū)動模式的系統(tǒng),當(dāng)用戶觸發(fā)了某個事件很魂,系統(tǒng)會快速的進(jìn)行響應(yīng)處理讶泰。一般的線程都是從開始直接走到結(jié)束的一個直線型的過程咏瑟,結(jié)束后線程就被釋放了。而RunLoop的存在就是為了能保持線程的持續(xù)存在痪署,當(dāng)有需要的時候進(jìn)行激活處理事件码泞,不需要的時候進(jìn)行掛起休眠等待下一次的事件激活。

普通的線程
添加RunLoop的線程

RunLoop的作用
1狼犯、使程序一直保持運行并能在用戶有輸入操作的時候進(jìn)行處理
2余寥、決定程序在任何應(yīng)該處理哪些事情
3、調(diào)用解耦悯森,消息隊列
4宋舷、節(jié)省CPU時間(在沒有需要處理的消息的時候進(jìn)行掛起休眠)

這里對2、3進(jìn)行解釋一下瓢姻,當(dāng)用戶進(jìn)行操作APP的時候肯定不是僅僅觸發(fā)某一個事件的祝蝠,必定是會觸發(fā)一系列的事件。這時候RunLoop會有個管理的消息隊列來做管理幻碱,先處理哪個再處理哪個绎狭。這時候用戶的消息觸發(fā)與程序的處理其實就解耦分開了,用戶只需要做自己的操作褥傍,剩下的都交給程序自己去做管理處理儡嘶。

RunLoop的機制
在我們運行的APP中打上斷點并進(jìn)行觸發(fā),看看調(diào)用棧

調(diào)用堆棧

我現(xiàn)在是斷在了一個button的點擊觸發(fā)事件那里恍风。我們看看調(diào)用堆棧里面的調(diào)用順序蹦狂。
最下面的start,main是整個程序的起調(diào)誓篱,然后到了UIKit里面的Main函數(shù),GSEventRunModel這個是物理內(nèi)核對用戶的點擊各種觸發(fā)事件的處理凯楔,然后就調(diào)到了RunLoop這里窜骄,獲取了點擊事件然后進(jìn)行事件消息處理分發(fā),到最上的就是我們熟悉的各種層層函數(shù)的調(diào)用啼辣。

我們這邊看到箭頭指的這個一長串東西啊研,其實是RunLoop的六種起調(diào)狀態(tài),我們的絕大部分都是從這六種狀態(tài)進(jìn)行調(diào)起的鸥拧,但也并不是絕對党远,如果自己創(chuàng)建一個線程去調(diào)用方法,是有可能不從這六個狀態(tài)進(jìn)行調(diào)起方法的

image.png

這里面的CAllING_OUT其實就可以看出來作用是進(jìn)行調(diào)出的富弦,主要看的是標(biāo)紅的地方
這邊解釋一下最下面兩個Source0和Source1
Source0:處理APP內(nèi)部事件沟娱,APP自己負(fù)責(zé)管理(觸發(fā))例如UIEvent
Source1:由RunLoop和內(nèi)核管理,Mach port驅(qū)動

Mach port
輕量級的進(jìn)程通訊腕柜,有點類似于網(wǎng)絡(luò)通訊端口济似,比方說手機的定位、網(wǎng)絡(luò)數(shù)據(jù)下載盏缤,都是手機通過調(diào)接口傳入到APP內(nèi)再調(diào)到相應(yīng)的函數(shù)

當(dāng)Xcode點擊暫停按鈕砰蠢,APP就會處于一個掛起的trap狀態(tài)
當(dāng)另一個線程(或者另一個進(jìn)程中的某個線程)向內(nèi)核發(fā)消息,trap狀態(tài)就會被喚醒唉铜,進(jìn)行事件處理

RunLoop的結(jié)構(gòu)

結(jié)構(gòu)

這張是從其他地方扒過來的圖

RunLoop與線程的關(guān)系
在我的理解中台舱,RunLoop是依托于線程的,但是并不是所有線程都會有RunLoop的潭流。線程剛創(chuàng)建時并沒有 RunLoop竞惋,如果你不主動獲取,那它一直都不會有灰嫉。RunLoop 的創(chuàng)建是發(fā)生在第一次獲取時拆宛,RunLoop 的銷毀是發(fā)生在線程結(jié)束時。你只能在一個線程的內(nèi)部獲取其 RunLoop(主線程除外)讼撒。

CFRunLoopTimer
NSTimer是對這個的一個上層封裝
除了GCD的timer其他的timer都是基于RunLoop來實現(xiàn)的

CFRunLoopSource
類似于一個協(xié)議Protocol浑厚,當(dāng)符合條件則觸發(fā)
在RunLoop里面自己定義了兩個,一個是Source0一個是Source1
聽說還可以自己定義椿肩,這里沒有仔細(xì)研究

CFRunLoopObserver

枚舉

向外部報告現(xiàn)在的狀態(tài)

這個與Autorelease Pool的關(guān)系
Autorelease Pool
在App啟動后, 系統(tǒng)會在主線程里先注冊兩個Observer, 回調(diào)都是_wrapRunLoopWithAutoreleasePoolHandler()
Observer1: 監(jiān)視即將進(jìn)入RunLoop, 在這個回調(diào)內(nèi)會去調(diào)用_objc_autoreleasePoolPush()來創(chuàng)建一個自動釋放池, 它的order是-2147483647, 最高優(yōu)先級, 醬紫就可以保證創(chuàng)建自動釋放池是在其他回調(diào)之前
Observer2: 監(jiān)聽了兩件事
第一: 在即將進(jìn)入休眠(BeforeWaiting)的時候調(diào)用_objc_autoreleasePoolPop()和_objc_autoreleasePoolPush()
第二: 在即將退出RunLoop(Exit)的時候調(diào)用_objc_autoreleasePoolPop()來釋放自動釋放池
注意: 這個Observer2的order是2147483647, 優(yōu)先級最低, 醬紫就可以保證在處理完所有事情之后再去釋放這個自動釋放池
我們在主線程中執(zhí)行的代碼, 一般都是寫在事件回調(diào), Timer回調(diào)內(nèi), 醬紫回調(diào)就會被RunLoop所創(chuàng)建的自動釋放池(Autorelease Pool)里循環(huán)著, 我們不用去擔(dān)心內(nèi)存泄漏什么之類的, 也不需要去顯示的去創(chuàng)建Pool

Mode
一個 RunLoop 包含若干個 Mode瞻颂,每個 Mode 又包含若干個 Source/Timer/Observer。每次調(diào)用 RunLoop 的主函數(shù)時郑象,只能指定其中一個 Mode,這個Mode被稱作 CurrentMode茬末。如果需要切換 Mode厂榛,只能退出 Loop盖矫,再重新指定一個 Mode 進(jìn)入。這樣做主要是為了分隔開不同組的 Source/Timer/Observer击奶,讓其互不影響辈双。

RunLoop與GCD
RunLoop和GCD其實是協(xié)調(diào)的關(guān)系,當(dāng)GCD觸發(fā)在主線程dispatch_get_main_queue()做事情的時候柜砾,RunLoop做的是幫GCD進(jìn)行調(diào)起

實踐
1湃望、保持線程的長久存活
2、通過切換mode來進(jìn)行不同事件的調(diào)用時機控制

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末痰驱,一起剝皮案震驚了整個濱河市证芭,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌担映,老刑警劉巖废士,帶你破解...
    沈念sama閱讀 218,755評論 6 507
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異蝇完,居然都是意外死亡官硝,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,305評論 3 395
  • 文/潘曉璐 我一進(jìn)店門短蜕,熙熙樓的掌柜王于貴愁眉苦臉地迎上來氢架,“玉大人,你說我怎么就攤上這事朋魔♂校” “怎么了?”我有些...
    開封第一講書人閱讀 165,138評論 0 355
  • 文/不壞的土叔 我叫張陵铺厨,是天一觀的道長缎玫。 經(jīng)常有香客問我,道長解滓,這世上最難降的妖魔是什么赃磨? 我笑而不...
    開封第一講書人閱讀 58,791評論 1 295
  • 正文 為了忘掉前任,我火速辦了婚禮洼裤,結(jié)果婚禮上邻辉,老公的妹妹穿的比我還像新娘。我一直安慰自己腮鞍,他們只是感情好值骇,可當(dāng)我...
    茶點故事閱讀 67,794評論 6 392
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著移国,像睡著了一般吱瘩。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上迹缀,一...
    開封第一講書人閱讀 51,631評論 1 305
  • 那天使碾,我揣著相機與錄音蜜徽,去河邊找鬼。 笑死票摇,一個胖子當(dāng)著我的面吹牛拘鞋,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播矢门,決...
    沈念sama閱讀 40,362評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼盆色,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了祟剔?” 一聲冷哼從身側(cè)響起隔躲,我...
    開封第一講書人閱讀 39,264評論 0 276
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎峡扩,沒想到半個月后蹭越,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,724評論 1 315
  • 正文 獨居荒郊野嶺守林人離奇死亡教届,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,900評論 3 336
  • 正文 我和宋清朗相戀三年响鹃,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片案训。...
    茶點故事閱讀 40,040評論 1 350
  • 序言:一個原本活蹦亂跳的男人離奇死亡买置,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出强霎,到底是詐尸還是另有隱情忿项,我是刑警寧澤,帶...
    沈念sama閱讀 35,742評論 5 346
  • 正文 年R本政府宣布城舞,位于F島的核電站轩触,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏家夺。R本人自食惡果不足惜脱柱,卻給世界環(huán)境...
    茶點故事閱讀 41,364評論 3 330
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望拉馋。 院中可真熱鬧榨为,春花似錦、人聲如沸煌茴。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,944評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽蔓腐。三九已至矩乐,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間回论,已是汗流浹背绰精。 一陣腳步聲響...
    開封第一講書人閱讀 33,060評論 1 270
  • 我被黑心中介騙來泰國打工撒璧, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留透葛,地道東北人笨使。 一個月前我還...
    沈念sama閱讀 48,247評論 3 371
  • 正文 我出身青樓,卻偏偏與公主長得像僚害,于是被迫代替她去往敵國和親硫椰。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 44,979評論 2 355

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