Runloop概念
- 運行循環(死循環)
Runloop作用
- 保持程序的持續運行
- 處理app中的各種事件
- 節省CPU資源,提升性能
Runloop處理邏輯圖
Runloop對象和線程
- 每條線程都有唯一的一個與之對應的Runloop對象
- 主線程的Runloop已經自動創建好了,子線程的Runloop需要主動創建
- Runloop在第一次獲取時創建,在線程結束時銷毀
Runloop對象獲取
-
Foundation
[NSRunLoop currentRunLoop]; // 獲取當前對象的Runloop對象 [NSRunLoop mainRunLoop]; // 獲取主線程的Runloop對象
-
Core Foundation
CFRunLoopGetCurrent(); // 獲取當前對象的Runloop對象 CFRunLoopGetMain(); // 獲取主線程的Runloop對象
CFRunLoopModeRef(Runloop運行模式)
一個Runloop包含若干個Mode,每個mode有包含若干個Source/Timer/Observer。
每次Runloop啟動時,只能指定其中一個Mode,這個Mode被稱作CurrentMode。
如果需要切換Mode,只能退出Loop,在重新指定一個Mode進入。這樣做主要是為了分隔不同組Source/Timer/Observer,讓其互不影響。
runloop.jpg
系統默認注冊5個Mode
- kCFRunLoopDefaultMode:APP的默認Mode,通常主線程是在這個Mode下運行
- UITrackingRunLoopMode:界面跟蹤Mode,用于ScrollView追蹤觸摸滑動,保證界面滑動時不受其他Mode影響
- UIInitializationRunLoopMode:在APP啟動時進入的第一個Mode,啟動完成后就不在使用了
- GSEventReceiveRunLoopMode:接受系統事件的內部Mode,通常用不到
- kCFRunLoopCommonModes:這是一個占位用的Mode,不是一種真正的Mode
CFRunLoopTimerRef
- 基于時間的觸發器
- 基本上說的就是NSTimer
CFRunLoopSourceRef
- 事件源(輸入源)
- Source0:非基于port的 用戶事件
- Source1:基于port的 系統事件
RunLoop內部自動釋放池
- 自動釋放池第一次常見:當runloop啟動的時候
- 自動釋放池最后一次銷毀:當runloop退出的時候
- 自動釋放池其它時間的創建和銷毀:當runloop即將休眠時銷毀之前的自動釋放池,創建新的釋放池
RunLoop應用
- performSelector 受RunLoop運行模式影響
- 線程任務
RunLoop常見面試題
-
什么是Runloop?
- 從字面意思來看:運行循環
- 其實它內部是do-while循環,在這個循環內不斷地處理各種任務(比如Source、Timer、Observer)
- 一線線程對應一個Runloop,主線程Runloop默認UI經啟動,子線程的Runloop需要手動啟動(調用run方法)
- Runloop只能選擇一個Mode啟動,如果當前Mode中沒有Source(Sources0、Sources0)、Timer,那么就直接退出Runloop
-
自動釋放池什么時候釋放?
- 通過Observer監聽Runloop的狀態
-
在開發中如何使用Runloop?什么應用場景?
- 開啟一個常駐線程(讓一個子線程不進入消亡狀態,等待其他線程發來消息,處理其他事件)
- 在子線程中開啟一個定時器
- 在子線程中進行一些長期監控
- 可以監控定時器在特定模式下執行
- 可以讓某些事件(行為、任務)在特定模式下執行
- 可以添加Observer監聽Runloop的狀態,比如監聽點擊事件的處理(在點擊之前做一些事情)