什么是RunLoop
從字面意思看
運行循環(huán)
跑圈
基本作用
- 保持程序的持續(xù)運行
- 處理App中的各種事件(比如觸摸事件樟澜、定時器事件琐旁、Selector事件)
- 節(jié)省CPU資源涮阔,提高程序性能:該做事時做事,該休息時休息
......
如果沒有RunLoop
int main(int argc, char * argv[]) {
NSLog(@"execute main function");
return 0;
}
- 沒有RunLoop的情況下
- 第3行后程序就結束了
如果有了RunLoop
int main(int argc, char * argv[]) {
BOOL running = YES;
do {
// 執(zhí)行各種任務灰殴,處理各種事件
// ......
} while (running);
return 0;
}
- 有RunLoop的情況下
- 由于main函數(shù)里面啟動了個RunLoop敬特,所以程序并不會馬上退出,保持持續(xù)運行狀態(tài)
main函數(shù)中的RunLoop
int main(int argc, char * argv[]) {
@autoreleasepool {
return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class]));
}
}
- UIApplicationMain函數(shù)內部就啟動了一個RunLoop
- 所以UIApplicationMain函數(shù)一直沒有返回牺陶,保持了程序的持續(xù)運行
- 這個默認啟動的RunLoop是跟主線程相關聯(lián)的
RunLoop對象
iOS中有2套API來訪問和使用RunLoop
Foundation
NSRunLoop
Core Foundation
CFRunLoopRef
NSRunLoop和CFRunLoopRef都代表著RunLoop對象
NSRunLoop是基于CFRunLoopRef的一層OC包裝伟阔,所以要了解RunLoop內部結構,需要多研究CFRunLoopRef層面的API(Core Foundation層面)
蘋果官方文檔
CFRunLoopRef是開源的
http://opensource.apple.com/source/CF/CF-1151.16/
RunLoop與線程
每條線程都有唯一的一個與之對應的RunLoop對象
主線程的RunLoop已經自動創(chuàng)建好了掰伸,子線程的RunLoop需要主動創(chuàng)建
RunLoop在第一次獲取時創(chuàng)建皱炉,在線程結束時銷毀
獲得RunLoop對象
Foundation
[NSRunLoop currentRunLoop]; // 獲得當前線程的RunLoop對象
[NSRunLoop mainRunLoop]; // 獲得主線程的RunLoop對象
Core Foundation
CFRunLoopGetCurrent(); // 獲得當前線程的RunLoop對象
CFRunLoopGetMain(); // 獲得主線程的RunLoop對象
RunLoop相關類
- Core Foundation中關于RunLoop的5個類
- CFRunLoopRef
- CFRunLoopModeRef
- CFRunLoopSourceRef
- CFRunLoopTimerRef
- CFRunLoopObserverRef
CFRunLoopModeRef
CFRunLoopModeRef代表RunLoop的運行模式
一個 RunLoop 包含若干個 Mode,每個Mode又包含若干個Source/Timer/Observer
每次RunLoop啟動時狮鸭,只能指定其中一個 Mode合搅,這個Mode被稱作 CurrentMode
如果需要切換Mode,只能退出Loop歧蕉,再重新指定一個Mode進入
這樣做主要是為了分隔開不同組的Source/Timer/Observer灾部,讓其互不影響
CFRunLoopModeRef
系統(tǒng)默認注冊了5個Mode:
kCFRunLoopDefaultMode:App的默認Mode,通常主線程是在這個Mode下運行
UITrackingRunLoopMode:界面跟蹤 Mode惯退,用于 ScrollView 追蹤觸摸滑動赌髓,保證界面滑動時不受其他 Mode 影響
UIInitializationRunLoopMode: 在剛啟動 App 時第進入的第一個 Mode,啟動完成后就不再使用
GSEventReceiveRunLoopMode: 接受系統(tǒng)事件的內部 Mode催跪,通常用不到
kCFRunLoopCommonModes: 這是一個占位用的Mode锁蠕,不是一種真正的Mode
CFRunLoopSourceRef
- CFRunLoopSourceRef是事件源(輸入源)
以前的分法 - Port-Based Sources
- Custom Input Sources
- Cocoa Perform Selector Sources
現(xiàn)在的分法 - Source0:非基于Port的
- Source1:基于Port的
CFRunLoopTimerRef
CFRunLoopTimerRef是基于時間的觸發(fā)器
基本上說的就是NSTimer
CFRunLoopObserverRef
CFRunLoopObserverRef是觀察者,能夠監(jiān)聽RunLoop的狀態(tài)改變
可以監(jiān)聽的時間點有以下幾個