什麼是 RunLoop
-
應用範疇
- 定時器、PerformSelector
- GCD Async Main Queue
- 事件響應、手勢識別、介面重新整理
- 網路請求
- AutoreleasePool
-
RunLoop的基本作用
- 保持程式的持續執行
- 處理 App 中的各種事件
- 節省CPU資源,提高程式效能:該做事時做事,該休息時休息
RunLoop物件
NSRunLoop 是基於 CFRunLoopRef 的一層 OC 包裝
RunLoop與執行緒
- 每條執行緒都有唯一的一個與之對應的 RunLoop物件
- RunLoop 儲存在一個全域性的 Dictionary裡,執行緒作為 key,RunLoop 作為 value
- 執行緒剛建立時並沒有 RunLoop物件,RunLoop 會在第一次獲取它時建立
- RunLoop會線上程結束時銷燬
- 主執行緒 RunLoop 自動獲取,子執行緒預設沒有開啟 RunLoop(這個就是你在子執行緒只開啟runloop他仍然會退出的原因)
RunLoop相關的類
- CFRunLoopRef
- CFRunLoopModeRef
- CFRunLoopSourceRef
- CFRunLoopTimerRef
- CFRunLoopObserverRef
struct __CFRunLoop {
pthread_t _pthread;
CFMutableSetRef _commonModes;
CFMutableSetRef _commonModeItems;
CFRunLoopModeRef _currentMode;
CFMutableSetRef _modes;
}
struct __CFRunLoopMode {
CFStringRef _name;
CFMutableSetRef _sources0;
CFMutableSetRef _sources1;
CFMutableArrayRef _observers;
CFMutableArrayRef _timers;
}
複製程式碼
CFRunLoopModeRef
- CFRunLoopModeRef 代表 RunLoop 的執行模式
- 一個 RunLoop 包含若干個 Mode,每個 Mode 又包含若干個 Source0/Source1/Timer/Observer
- RunLoop啟動時只能選擇其中一個 Mode,作為 currentMode
- 如果需要切換Mode,只能退出當前 Loop,再重新選擇一個 Mode 進入,不同組的Source0/Source1/Timer/Observer能分隔開,互不影響
- 如果 Mode 裡沒有任何 Source0/Source1/Timer/Observer,RunLoop會立馬退出
- 常見的兩種 Mode
- kCFRunLoopDefaultMode(NSDefaultRunLoopMode):App預設的Mode,通常主執行緒是在這個Mode下執行
- UITrackingRunLoopMode:介面跟蹤 Mode,用於 ScrollView 追蹤觸控滑動,保證介面滑動時不受其他 Mode影響
RunLoop的執行邏輯
-
Source0
- 觸控事件處理
- performSelector:onThread:
-
Source1
- 基於 Port 的執行緒間通訊
- 系統事件的捕捉
-
Timers
- NSTimer
- performSelector:withObject:afterDelay:
-
Observers
- 用於監聽 RunLoop 的狀態
- UI重新整理(BeforeWaiting)
- AutoreleasePool(BeforeWaiting)
休眠的細節
使用者態呼叫mach_msg(),就會切換到核心態去真正執行mach_msg(),讓執行緒等待訊息(沒有訊息讓執行緒休眠,有訊息就喚醒執行緒)
執行緒保活
[[NSRunLoop currentRunLoop] run]是無法停止的,它專門用於開啟一個永不銷燬的執行緒(NSRunLoop)
複製程式碼