RunLoop問題集

什么是RunLoop?

答:RunLoop是線程相關的基礎框架中的一部分,是一個事件處理對象,每一個線程都有與之對應的RunLoop,但并不是線程創建時就有RunLoop,只有當前線程第一次主動獲取RunLoop,系統才會創建當前線程相應的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的操作最終都會轉換成對CFRunLoopRef的操作,但需要注意的是,NSRunLoop與CFRunLoopRef并不是簡單的接口轉換,就像啟動RunLoop一樣,NSRunLoop的Run方法與CFRunLoopRun()并不是對應著的,而且有著一定的區別。

NSRunLoop Run
CFRunLoopRun()

如何退出RunLoop?

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

方式一是官法推薦的方式,可以安全有效地退出RunLoop。方式二,用CFRunLoopStop()函數并不是絕對可以退出Run的,要看以什么方式啟動RunLoop,如果用[[NSRunLoop currentRunLoop] run]來啟動RunLoop,那么用CFRunLoopStop()是無法退出RunLoop的,正如上面的偽代碼所示,以[[NSRunLoop currentRunLoop] run]啟動的RunLoop,唯一退出的方式是移除CurrentMode的所有輸入源和定時源,也就是方式三,但這種方式是不穩定的,因為系統會添加一些輸入源或定時源來完成一些操作。

RunLoop是否自動運行的?

答:所有線程的RunLoop都是默認不啟動的,但主線程的RunLoop會隨著應用的運行而被啟動。

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

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

什么是RunLoopMode?

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

RunLoop每次進入Run時都需要指定一個RunLoopMode,指定RunLoopMode后,只有當前RunLoopMode內的源和觀察者會被處理,其它的源和觀察者需要等到RunLoop運行其RunLoopMode時才會被處理,切換RunLoopMode的唯一方式是,退出當前RunLoopMode,重新指定一個RunLoopMode進入Run。當RunLoop選擇一個RunLoopMode進入Run時,若這個RunLoopMode中并沒有需要處理的源(輸入源或定時源),RunLoop就會直接退出。

RunLoopMode

RunLoopMode中的_timerPort是_timers中所有定時源的公共Port,_portToV1SourceMap記錄了_sources1以及對應的Port,通過Port獲取相應的Source1。

通過Port獲取Source1

什么是CommonMode和CommonModeItem?

答:CommonModeItem是公共ModeItem,CommonMode是公共RunLoopMode,當把一個RunLoopMode注冊為CommonMode時,CommonModeItem被會自動添加到CommonMode里,當CommonModeItem有所改動時,CommonMode也會作出相應的改動。

什么是定時源(Timer Source)?

答:用于延時或重復的時間間隔處理事件。

如何使用定時源?

答:CFRunLoopTimerRef是RunLoop中唯一的定時源,以定時器的形式表示和使用,可選擇的定時器有,NSTimer,CADisplayLink,CFRunLoopTimerRef,GCD Timer。

四種定時器的區別是什么?

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

GCD Timer調用棧

GCD Timer有別于前三種定時器,是由GCD系統所管理的定時器,通過一定的時間間隔dispatch任務到相應的隊列中處理,以主線程為例,時間間隔到達后,GCD系統將Block dispatch到主線程對應的Main Queue,等待Main RunLoop檢測和處理。

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

答:除非需要實現定時動畫,否則不建議使用CADisplayLink作為定時器(具體請看iOS10定時消息的改動。什么是定時動畫?請查看iOS動畫的基礎知識);NSTimer適用于大部份情況,但需要注意循環引用的問題;GCD Timer的缺點在于,不能在自己所創建的子線程中使用。

CFRunLoopTimerRef的觸發原理是怎樣的?

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

什么是輸入源?

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

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

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

? ? ?2).Source0與Source1都可用于線程(或進程)交互,但交互的形式有所不同,Source1監聽端口,當端口有消息到達時,相應的Source1就會被觸發回調,完成相應的操作;而Source0并不監聽端口,讓Source0執行回調需要手動標記Source0為待處理狀態,還需要呼醒Source0所在的RunLoop。

Source1交互
Source0交互

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

? ? ? 4).一次Loop只能執行一個Source1的回調,但一次Loop可以執行多個待處理的Source0的回調。

如何創建Source0?

創建Source0

如何標記Source為待處理狀態,且呼醒所在的RunLoop?

Source0交互

如何創建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接收和發送需要是同一個對象;CFMessagePortRef接收和發送的Port所用的name要相同,CFMessagePortSendRequest()函數通過CFMessagePortRef的name來查找相應的接收端口來進行消息發送(不建議直接使用mach_msg()來發送消息,關于Port可以查看Inter-Process Communication)。

RunLoop的內部邏輯是怎樣的?

Run內部邏輯
官方文檔的Run內部邏輯

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

CFRunLoop Run源碼第五步

從源碼可以看到,第五步檢測的是GCD端口事件,而不是官方文檔所寫的基于端口的輸入源,但經過大量測試發現,第五步實際上會檢測所有未處理的端口事件,而并非像官方文檔或源碼所展示的那樣(太坑爹了,居然官方文檔跟源碼不同,源碼又和實際測試結果不同??)。

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

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 228,505評論 6 533
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 98,556評論 3 418
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 176,463評論 0 376
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 63,009評論 1 312
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 71,778評論 6 410
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 55,218評論 1 324
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,281評論 3 441
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 42,436評論 0 288
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 48,969評論 1 335
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 40,795評論 3 354
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 42,993評論 1 369
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,537評論 5 359
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 44,229評論 3 347
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,659評論 0 26
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 35,917評論 1 286
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 51,687評論 3 392
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 47,990評論 2 374

推薦閱讀更多精彩內容