- 是通過內(nèi)部維護的
事件循環(huán)
來對事件/消息
進行管理的一個對象
- 基本作用
- 保持程序的持續(xù)運行
- 處理App中的各種事件(比如觸摸事件粱坤、定時器事件氏淑、Selector事件)
- 節(jié)省CPU資源识藤,提高程序性能:該做事時做事莺戒,該休息時休息
- main函數(shù)中的RunLoop
int main(int argc, char * argv[]) {
@autoreleasepool {
return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class]));
}
}
// 第三行代碼的UIApplicationMain函數(shù)內(nèi)部就啟動了一個RunLoop懊昨,所以UIApplicationMain函數(shù)一直沒有返回,保持了程序的持續(xù)運行迅皇,這個函數(shù)啟動的RunLoop是跟主線程相關(guān)聯(lián)的
- RunLoop對象
- iOS有2套API來訪問和使用RunLoop
- Foundation(OC)
NSRunLoop
- Core Foundation(C語言)
CFRunLoopRef
- RunLoop與線程
- 每條線程都有唯一的一個與之對應(yīng)的RunLoop對象
- 主線程的RunLoop已經(jīng)自動創(chuàng)建好了昧辽,子線程的RunLoop需要手動創(chuàng)建
- RunLoop在第一次獲取時間創(chuàng)建,在線程結(jié)束時銷毀
- 獲得RunLoop對象
- Foundation
[NSRunLoop currentRunLoop];// 獲得當前線程的RunLoop對象
[NSRunLoop mainRunLoop];// 獲得主線程的RunLoop對象
- Core Foundation
CFRunLoopGetCurrent();// 獲得當前線程的RunLoop對象
CFRunLoopGetMain();// 獲得主線程的RunLoop對象
- RunLoop相關(guān)類
- CFRunLoopRef
- CFRunLoopModeRef
- CFRunLoopSourceRef
- CFRunLoopTimerRef
- CFRunLoopObserverRef
- CFRunLoopModeRef
- CFRunLoopModeRef代表RunLoop的運行模式
- 一個RunLoop包含若干個Mode登颓,每個Mode又包含若干個Source/Timer/Observer
- 每次RunLoop啟動時搅荞,只能指定其中一個Mode,這個Mode被稱為CurrentMode
- 如果需要切換Mode框咙,只能退出RunLoop咕痛,再重新指定一個Mode進入
- 這樣做主要是為了分割開不同組的Source/Timer/Observer,讓其互不影響
- 系統(tǒng)默認注冊了5個Mode
- kCFRunLoopDefaultMode:App的默認Mode喇嘱,通常主線程是在這個Mode下運行
- UITrackingRunLoopMode:界面跟蹤Mode茉贡,用于Scrollview追蹤觸摸滑動,保證界面滑動時不受其他Mode影響
- UIInitializationRunLoopMode:在剛啟動App時進入的第一個Mode者铜,啟動完成后就不再使用
- GSEventReceiveRunLoopMode:接受系統(tǒng)事件的內(nèi)部Mode腔丧,通常用不到
- kCFRunLoopCommonModes:這是一個占位的Mode放椰,不是一種真正的Mode
- CFRunLoopSourceRef
- CFRunLoopSourceRef是事件源(輸入源)
- Source0:非基于Port的
- Source1:基于Port的
- CFRunLoopTimerRef
- CFRunLoopTimerRef是基于時間的觸發(fā)器
- 基本上說的就是NSTimer
- CFRunLoopObserverRef
- CFRunLoopObserverRef是觀察者,能夠監(jiān)聽RunLoop的狀態(tài)改變
- 可以監(jiān)聽的時間有以下幾個:
typedef CF_OPTIONS(CFOptionFlags, CFRunLoopActivity) {
kCFRunLoopEntry = (1UL << 0),
kCFRunLoopBeforeTimers = (1UL << 1),
kCFRunLoopBeforeSources = (1UL << 2),
kCFRunLoopBeforeWaiting = (1UL << 5),
kCFRunLoopAfterWaiting = (1UL << 6),
kCFRunLoopExit = (1UL << 7),
kCFRunLoopAllActivities = 0x0FFFFFFFU
};
- RunLoop處理邏輯
RunLoop的事件隊列
每次運行RunLoop愉粤,線程的RunLoop會自動處理之前未處理的消息砾医,并通知相關(guān)的觀察者。具體的順序如下
- 通知觀察者RunLoop已經(jīng)啟動
- 通知觀察者任何即將要開始的定時器
- 通知觀察者任何即將啟動的非基于端口的源
- 啟動任何準備好的非基于端口的源
- 如果基于端口的源準備好并處于等待狀態(tài)衣厘,立即啟動如蚜,并進入步驟9
- 通知觀察者線程進入休眠
- 將線程置于休眠直到任一下面的事件發(fā)生
- 某一事件到達基于端口的源
- 定時器啟動
- RunLoop設(shè)置的時間已經(jīng)超時
- RunLoop被顯式喚醒
- 通知觀察者線程將被喚醒
- 處理未處理的事件
- 如果用戶定義的定時器啟動,處理定時器事件并重啟RunLoop影暴。進入步驟2
- 如果輸入源啟動错邦,傳遞相應(yīng)的消息
- 如果RunLoop被顯式喚醒而且時間還沒超時,重啟RunLoop坤检。進入步驟2
- 通知觀察者RunLoop結(jié)束
最后編輯于 :
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者