iOS RunLoop(1)RunLoop簡介
iOS RunLoop(2)RunLoop相關(guān)類
iOS RunLoop(3)RunLoop原理
iOS RunLoop(4)RunLoop實戰(zhàn)應(yīng)用
RunLoop簡介
什么是RunLoop?
可以理解為字面意思:Run表示運(yùn)行,Loop表示循環(huán)。結(jié)合在一起就是運(yùn)行的循環(huán)的意思。哈哈,我更愿意翻譯為『跑圈』。直觀理解就像是不停的跑圈。
RunLoop實際上是一個對象,這個對象在循環(huán)中用來處理程序運(yùn)行過程中出現(xiàn)的各種事件(比如說觸摸事件、UI刷新事件、定時器事件、Selector事件),從而保持程序的持續(xù)運(yùn)行;而且在沒有事件處理的時候,會進(jìn)入睡眠模式,從而節(jié)省CPU資源,提高程序性能。
RunLoop和線程
首先,iOS 開發(fā)中能遇到兩個線程對象: pthread_t 和 NSThread。過去蘋果有份文檔標(biāo)明了 NSThread 只是 pthread_t 的封裝,但那份文檔已經(jīng)失效了,現(xiàn)在它們也有可能都是直接包裝自最底層的 mach thread。蘋果并沒有提供這兩個對象相互轉(zhuǎn)換的接口,但不管怎么樣,可以肯定的是 pthread_t 和 NSThread 是一一對應(yīng)的。比如,你可以通過 pthread_main_thread_np() 或 [NSThread mainThread] 來獲取主線程;也可以通過 pthread_self() 或 [NSThread currentThread] 來獲取當(dāng)前線程。CFRunLoop 是基于 pthread 來管理的。
蘋果不允許直接創(chuàng)建 RunLoop,它只提供了兩個自動獲取的函數(shù):CFRunLoopGetMain() 和 CFRunLoopGetCurrent()。
一條線程對應(yīng)一個RunLoop對象,每條線程都有唯一一個與之對應(yīng)的RunLoop對象。
我們只能在當(dāng)前線程中操作當(dāng)前線程的RunLoop,而不能去操作其他線程的RunLoop。
RunLoop對象在第一次獲取RunLoop時創(chuàng)建,銷毀則是在線程結(jié)束的時候。
主線程的RunLoop對象系統(tǒng)自動幫助我們創(chuàng)建好了(原理如下),而子線程的RunLoop對象需要我們主動創(chuàng)建。
默認(rèn)情況下主線程的RunLoop原理
我們在啟動一個iOS程序的時候,系統(tǒng)會調(diào)用創(chuàng)建項目時自動生成的main.m的文件。main.m文件如下所示:
int main(int argc, char * argv[]) {
@autoreleasepool {
return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class]));
}
}
其中UIApplicationMain函數(shù)內(nèi)部幫我們開啟了主線程的RunLoop,UIApplicationMain內(nèi)部擁有一個無線循環(huán)的代碼。上邊的代碼中開啟RunLoop的過程可以簡單的理解為如下代碼:
int main(int argc, char * argv[]) {
BOOL running = YES;
do {
// 執(zhí)行各種任務(wù),處理各種事件
// ......
} while (running);
return 0;
}
從上邊可看出,程序一直在do-while循環(huán)中執(zhí)行,所以UIApplicationMain函數(shù)一直沒有返回,我們在運(yùn)行程序之后程序不會馬上退出,會保持持續(xù)運(yùn)行狀態(tài)。
下圖是蘋果官方給出的RunLoop模型圖。
從上圖中可以看出,RunLoop就是線程中的一個循環(huán),RunLoop在循環(huán)中會不斷檢測,通過Input sources(輸入源)和Timer sources(定時源)兩種來源等待接受事件;然后對接受到的事件通知線程進(jìn)行處理,并在沒有事件的時候進(jìn)行休息。
文章來源:
http://www.itdecent.cn/p/d260d18dd551
https://blog.ibireme.com/2015/05/18/runloop/