RunLoop問題集

什么是RunLoop?

答:RunLoop是線程相關(guān)的基礎(chǔ)框架中的一部分,是一個事件處理對象丸边,每一個線程都有與之對應(yīng)的RunLoop典格,但并不是線程創(chuàng)建時就有RunLoop,只有當(dāng)前線程第一次主動獲取RunLoop抵皱,系統(tǒng)才會創(chuàng)建當(dāng)前線程相應(yīng)的RunLoop善榛。

RunLoop的作用是什么?

答:1).管理線程的生命周期及活動呻畸。 ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ??

? ? ?2).處理輸入事件源以及通知觀察者移盆。

如何使用RunLoop?

答:iOS/OSX提供了Core Foundation(CFRunLoopRef)和Cocoa(NSRunLoop)兩套API來使用RunLoop,可以通過CFRunLoopGetMain() 和 CFRunLoopGetCurrent()或[NSRunLoop mainRunLoop]和[NSRunLoop currentRunLoop]來獲取RunLoop對象伤为,NSRunLoop是基于CFRunLoopRef的高層組件咒循,CFRunLoopRef的API都是線程安全的,但NSRunLoop的API不是線程安全的绞愚。雖然CFRunLoopRef的操作都是線程安全的叙甸,但不建議跨線程處理。

如何啟動RunLoop位衩?

答:可以通過NSRunLoop對象的run裆蒸,runUntilDate:,runMode:beforeDate:方法糖驴,或通過CFRunLoopRef的CFRunLoopRun()僚祷,CFRunLoopRunInMode()來啟動RunLoop。

使用NSRunLoop和CFRunLoopRef來啟動RunLoop有何不同遂赠?

答:雖然NSRunLoop是基于CFRunLoopRef的高層組件,對NSRunLoop的操作最終都會轉(zhuǎn)換成對CFRunLoopRef的操作晌杰,但需要注意的是跷睦,NSRunLoop與CFRunLoopRef并不是簡單的接口轉(zhuǎn)換,就像啟動RunLoop一樣肋演,NSRunLoop的Run方法與CFRunLoopRun()并不是對應(yīng)著的抑诸,而且有著一定的區(qū)別。

NSRunLoop Run
CFRunLoopRun()

如何退出RunLoop爹殊?

答:退出RunLoop的方式有三種蜕乡,分別是:方式一.給RunLoop設(shè)定超時時間;方式二.使用CFRunLoopStop()函數(shù)顯式退出梗夸;方式三.移除CurrentMode的所有輸入源和定時源层玲。

方式一是官法推薦的方式,可以安全有效地退出RunLoop反症。方式二辛块,用CFRunLoopStop()函數(shù)并不是絕對可以退出Run的,要看以什么方式啟動RunLoop铅碍,如果用[[NSRunLoop currentRunLoop] run]來啟動RunLoop润绵,那么用CFRunLoopStop()是無法退出RunLoop的,正如上面的偽代碼所示胞谈,以[[NSRunLoop currentRunLoop] run]啟動的RunLoop尘盼,唯一退出的方式是移除CurrentMode的所有輸入源和定時源憨愉,也就是方式三,但這種方式是不穩(wěn)定的卿捎,因?yàn)橄到y(tǒng)會添加一些輸入源或定時源來完成一些操作配紫。

RunLoop是否自動運(yùn)行的?

答:所有線程的RunLoop都是默認(rèn)不啟動的娇澎,但主線程的RunLoop會隨著應(yīng)用的運(yùn)行而被啟動笨蚁。

RunLoop處理的輸入事件源有哪些?

答:RunLoop處理的事件源有兩種趟庄,分別是輸入源(Input Source)和定時源(Timer Source)括细,而主線程的Main RunLoop還會處理GCD事件源。

什么是RunLoopMode戚啥?

答:RunLoop可以有多個RunLoopMode奋单,RunLoopMode包含了輸入源(Input Source),定時源(Timer Source)和觀察者(Observer)猫十。

RunLoop每次進(jìn)入Run時都需要指定一個RunLoopMode览濒,指定RunLoopMode后,只有當(dāng)前RunLoopMode內(nèi)的源和觀察者會被處理拖云,其它的源和觀察者需要等到RunLoop運(yùn)行其RunLoopMode時才會被處理贷笛,切換RunLoopMode的唯一方式是,退出當(dāng)前RunLoopMode宙项,重新指定一個RunLoopMode進(jìn)入Run乏苦。當(dāng)RunLoop選擇一個RunLoopMode進(jìn)入Run時,若這個RunLoopMode中并沒有需要處理的源(輸入源或定時源)尤筐,RunLoop就會直接退出汇荐。

RunLoopMode

RunLoopMode中的_timerPort是_timers中所有定時源的公共Port,_portToV1SourceMap記錄了_sources1以及對應(yīng)的Port盆繁,通過Port獲取相應(yīng)的Source1掀淘。

通過Port獲取Source1

什么是CommonMode和CommonModeItem?

答:CommonModeItem是公共ModeItem油昂,CommonMode是公共RunLoopMode革娄,當(dāng)把一個RunLoopMode注冊為CommonMode時,CommonModeItem被會自動添加到CommonMode里冕碟,當(dāng)CommonModeItem有所改動時稠腊,CommonMode也會作出相應(yīng)的改動。

什么是定時源(Timer Source)鸣哀?

答:用于延時或重復(fù)的時間間隔處理事件架忌。

如何使用定時源?

答:CFRunLoopTimerRef是RunLoop中唯一的定時源我衬,以定時器的形式表示和使用叹放,可選擇的定時器有饰恕,NSTimer,CADisplayLink井仰,CFRunLoopTimerRef埋嵌,GCD Timer。

四種定時器的區(qū)別是什么俱恶?

答:NSTimer和CADisplayLink是Cocoa提供的高層定時器雹嗦,CFRunLoopTimerRef是Core Foundation提供的基礎(chǔ)定時器,NSTimer和CADisplayLink是建立在CFRunLoopTimerRef之上的高層組件合是,而CFRunLoopTimerRef是建立在mk_timer之上了罪。NSTimer和CADisplayLink主要區(qū)別在于信號的發(fā)射頻率不同,CADisplayLink的信號發(fā)射頻率固定在16.67ms一次聪全,而NSTimer的信號發(fā)射頻率可自由定義(具體請看iOS10定時消息的改動)泊藕。

GCD Timer調(diào)用棧

GCD Timer有別于前三種定時器,是由GCD系統(tǒng)所管理的定時器难礼,通過一定的時間間隔dispatch任務(wù)到相應(yīng)的隊列中處理娃圆,以主線程為例,時間間隔到達(dá)后蛾茉,GCD系統(tǒng)將Block dispatch到主線程對應(yīng)的Main Queue讼呢,等待Main RunLoop檢測和處理。

如何選擇使用哪一種定時器谦炬?

答:除非需要實(shí)現(xiàn)定時動畫悦屏,否則不建議使用CADisplayLink作為定時器(具體請看iOS10定時消息的改動。什么是定時動畫吧寺?請查看iOS動畫的基礎(chǔ)知識)窜管;NSTimer適用于大部份情況散劫,但需要注意循環(huán)引用的問題稚机;GCD Timer的缺點(diǎn)在于,不能在自己所創(chuàng)建的子線程中使用获搏。

CFRunLoopTimerRef的觸發(fā)原理是怎樣的赖条?

答:具體請看iOS10定時消息的改動

什么是輸入源常熙?

答:是RunLoop所處理的事件源之一纬乍,主要用于線程或進(jìn)程交互,輸入源分為基于端口輸入源(Source1)和非端口輸入源(Source0)裸卫。

基于端口輸入源(Source1)與非端口輸入源(Source0)的區(qū)別是什么仿贬?

答:1).Source0與Source1都是CFRunLoopSourceRef類型,但配置方式不同墓贿,Source0用CFRunLoopSourceContext來配置茧泪,Source1用CFRunLoopSourceContext1來配置蜓氨。

? ? ?2).Source0與Source1都可用于線程(或進(jìn)程)交互,但交互的形式有所不同队伟,Source1監(jiān)聽端口穴吹,當(dāng)端口有消息到達(dá)時,相應(yīng)的Source1就會被觸發(fā)回調(diào)嗜侮,完成相應(yīng)的操作港令;而Source0并不監(jiān)聽端口,讓Source0執(zhí)行回調(diào)需要手動標(biāo)記Source0為待處理狀態(tài)锈颗,還需要呼醒Source0所在的RunLoop顷霹。

Source1交互
Source0交互

? ? ? 3).從Source0與Source1的交式方式了解到,Source1的交互會主動呼醒所在的RunLoop宜猜,而Source0的交互則需要依賴其它線程來呼醒Source0所在的RunLoop泼返。

? ? ? 4).一次Loop只能執(zhí)行一個Source1的回調(diào),但一次Loop可以執(zhí)行多個待處理的Source0的回調(diào)姨拥。

如何創(chuàng)建Source0?

創(chuàng)建Source0

如何標(biāo)記Source為待處理狀態(tài)绅喉,且呼醒所在的RunLoop?

Source0交互

如何創(chuàng)建Source1以及如何交互?

答:有Cocoa和Core Foundation兩套API來配置和使用Source1叫乌;Cocoa有NSPort柴罐,NSMachPort,NSMessagePort憨奸,NSSocketPort等類革屠,Core Foundation有CFMachPortRef,CFMessagePortRef排宰,CFSocketRef等似芝。其中用得比較多的是NSMachPort和CFMessagePortRef。

CFMessagePortRef
NSMachPort

Cocoa所提供的類只是建立在Core Foundation之上的高層組件板甘,且提供了toll-free bridged党瓮。需要注意的是,NSMachPort接收和發(fā)送需要是同一個對象盐类;CFMessagePortRef接收和發(fā)送的Port所用的name要相同寞奸,CFMessagePortSendRequest()函數(shù)通過CFMessagePortRef的name來查找相應(yīng)的接收端口來進(jìn)行消息發(fā)送(不建議直接使用mach_msg()來發(fā)送消息,關(guān)于Port可以查看Inter-Process Communication)在跳。

RunLoop的內(nèi)部邏輯是怎樣的枪萄?

Run內(nèi)部邏輯
官方文檔的Run內(nèi)部邏輯

需要注意的是第五步,官方文檔寫的是如果有基于端口的輸入源待處理猫妙,就進(jìn)入第九步瓷翻,這跟CFRunLoop的源碼不同。

CFRunLoop Run源碼第五步

從源碼可以看到,第五步檢測的是GCD端口事件齐帚,而不是官方文檔所寫的基于端口的輸入源元践,但經(jīng)過大量測試發(fā)現(xiàn),第五步實(shí)際上會檢測所有未處理的端口事件童谒,而并非像官方文檔或源碼所展示的那樣(太坑爹了单旁,居然官方文檔跟源碼不同,源碼又和實(shí)際測試結(jié)果不同??)饥伊。

如果有什么地方寫錯的麻煩指出象浑,如果有什么還想知道的請在評論留言,我會盡快補(bǔ)上的琅豆。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末愉豺,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子茫因,更是在濱河造成了極大的恐慌蚪拦,老刑警劉巖,帶你破解...
    沈念sama閱讀 219,490評論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件冻押,死亡現(xiàn)場離奇詭異驰贷,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)洛巢,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,581評論 3 395
  • 文/潘曉璐 我一進(jìn)店門括袒,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人稿茉,你說我怎么就攤上這事锹锰。” “怎么了漓库?”我有些...
    開封第一講書人閱讀 165,830評論 0 356
  • 文/不壞的土叔 我叫張陵恃慧,是天一觀的道長。 經(jīng)常有香客問我渺蒿,道長痢士,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,957評論 1 295
  • 正文 為了忘掉前任蘸嘶,我火速辦了婚禮良瞧,結(jié)果婚禮上陪汽,老公的妹妹穿的比我還像新娘训唱。我一直安慰自己,他們只是感情好挚冤,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,974評論 6 393
  • 文/花漫 我一把揭開白布况增。 她就那樣靜靜地躺著,像睡著了一般训挡。 火紅的嫁衣襯著肌膚如雪澳骤。 梳的紋絲不亂的頭發(fā)上歧强,一...
    開封第一講書人閱讀 51,754評論 1 307
  • 那天,我揣著相機(jī)與錄音为肮,去河邊找鬼摊册。 笑死,一個胖子當(dāng)著我的面吹牛颊艳,可吹牛的內(nèi)容都是我干的茅特。 我是一名探鬼主播,決...
    沈念sama閱讀 40,464評論 3 420
  • 文/蒼蘭香墨 我猛地睜開眼棋枕,長吁一口氣:“原來是場噩夢啊……” “哼白修!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起重斑,我...
    開封第一講書人閱讀 39,357評論 0 276
  • 序言:老撾萬榮一對情侶失蹤兵睛,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后窥浪,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體祖很,經(jīng)...
    沈念sama閱讀 45,847評論 1 317
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,995評論 3 338
  • 正文 我和宋清朗相戀三年漾脂,在試婚紗的時候發(fā)現(xiàn)自己被綠了突琳。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 40,137評論 1 351
  • 序言:一個原本活蹦亂跳的男人離奇死亡符相,死狀恐怖拆融,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情啊终,我是刑警寧澤镜豹,帶...
    沈念sama閱讀 35,819評論 5 346
  • 正文 年R本政府宣布,位于F島的核電站蓝牲,受9級特大地震影響趟脂,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜例衍,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,482評論 3 331
  • 文/蒙蒙 一昔期、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧佛玄,春花似錦硼一、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,023評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春哼蛆,著一層夾襖步出監(jiān)牢的瞬間蕊梧,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,149評論 1 272
  • 我被黑心中介騙來泰國打工腮介, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留肥矢,地道東北人。 一個月前我還...
    沈念sama閱讀 48,409評論 3 373
  • 正文 我出身青樓叠洗,卻偏偏與公主長得像橄抹,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子惕味,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,086評論 2 355

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