RunLoop

  • 概念
  • 數(shù)據(jù)結構
  • 事件循環(huán)機制
  • RunLoop 與 NSTimer
  • RunLoop 與多線程

一、概念

  • RunLoop是通過內部維護的事件循環(huán)對事件/消息進行管理的一個對象

事件循環(huán):

  • 沒有消息需要處理時,休眠以避免資源占用(用戶態(tài)--> 內核態(tài))
  • 有消息需要處理,立刻被喚醒(內核態(tài) --> 用戶態(tài))
系統(tǒng)調用相關指令如開關機等是在內核態(tài)的,程序一般運行在用戶態(tài)的,絕大部分API都是用戶態(tài)的
image

二、數(shù)據(jù)結構

NSRunLoop 是 CFRunLoop 的封裝,提供了面相對象的API,其數(shù)據(jù)結構如下:

  • CFRunLoop
  • CFRunLoopMode
  • Source/Timer/Observer

1、CFRunLoop

包含以下內容:

  • pthread --- (RunLoop和線程一一對應)
  • currentMode --- CFRunLoopMode
  • modes --- NSMutableSet<CFRunLoopMode*>
  • commonModes --- NSMutableSet<NSString*>
  • commonModeItems --- 也是一個集合,包含多個 Observer(觀察者)、Timer、Source

2、CFRunLoopMode

  • name --- 名稱,如 NSDefaultRunLoopMode 等
  • sources0 -- 集合類型,無序的
  • sources1 --- 集合類型
  • observers --- 數(shù)組,有序的
  • timers --- 數(shù)組

3、CFRunLoopSource

  • source0 --- 需要手動喚醒線程
  • source1 --- 具備喚醒線程的能力

4、CFRunLoopTimer

  • 基于事件的定時器,和 NSTimer 是 toll-free bridged的。(即可以橋轉換)

5、CFRunLoopObserver

觀測時間點:

  • kCFRunLoopEntry
  • kCFRunLoopBeforeTimers
  • kCFRunLoopBeforeSources
  • kCFRunLoopBeforeWaiting --- 即將休眠,即將切換內核狀態(tài)
  • kCFRunLoopAfterWaiting --- 內核態(tài)切換到用戶態(tài)不久之后發(fā)出
  • kCFRunLoopExit

各個數(shù)據(jù)結構之間的關系

一對多的關系:


image

RunLoop的Mode:

問題:怎樣將Timer同時添加到兩個mode?以保證mode切換的時候,不影響timer的使用
image
解決 :NSRunLoopCommonModes
NSRunLoopCommonModes的特殊性
  • commonMode 不是實際存在的一種Mode
  • 是同步 Source/Timer/Observer 到多個 Mode 中的一種技術方案

三、事件循環(huán)機制

image
APP運行生命周期內RunLoop的整體事件循環(huán)機制

RunLoop的核心

image

四、RunLoop 與 NSTimer

問題:滑動 TableView 時,定時器還會生效嗎?
回答:不會生效,timer 默認加入到 defaultMode 中,滑動的時候,Mode 會從 kCFRunLoopDefaultMode 切換到 UITrackingRunLoopMode,不同的 Mode ,timer 不相關,所以不生效
解決:添加到 kCFRunLoopCommonMode 中

五、RunLoop 與多線程

  • 線程是和 RunLoop 一一對應的
  • 自己創(chuàng)建的線程默認是沒有 RunLoop 的

怎樣實現(xiàn)一個常駐線程

  • 為當前線程開啟一個 RunLoop
  • 向該 RunLoop 中添加一個 Port/Source 等維持 RunLoop 的事件循環(huán)
  • 啟動該 RunLoop

代碼實現(xiàn):

運行的模式和資源添加的模式一定要是同一個
image

image

總結

  • 什么是 RunLoop ,是怎樣做到有事做事,沒事休息的?
  • RunLoop 與線程的關系?
  • 如何實現(xiàn)常駐線程?
  • 怎樣保證子線程數(shù)據(jù)回來更新UI的時候,不打斷用戶的滑動操作?(把子線程拋給主線程的操作添加到 DefaultMode 下,此時滑動 UITrackingRunLoopMode 不受影響)
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
【社區(qū)內容提示】社區(qū)部分內容疑似由AI輔助生成,瀏覽時請結合常識與多方信息審慎甄別。
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發(fā)布,文章內容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

友情鏈接更多精彩內容