Runloop基本來說就是一個事件處理的循環(huán),一般用來調度協(xié)調事件.
Runloop的目的就是當你的線程有任務的時候處理任務,當沒有任務的時候讓你的線程休眠.
Runloop 會接收兩種類型的Soure:
一種是InputSource (異步處理事件),一般用是其他線程來的消息,或者其他APP來的消息
一中是TimerSource(同步處理事件),被定時器調度產(chǎn)生的事件
上圖展示了一個線程的Runloop的處理事件的流程,當runloop處理InputSource時,會調用runUntilDate方法結束runloop.處理TimerSource事件的時候runloop不會結束.
Runloop Mode
Runloop Mode 就是一個監(jiān)聽InputSource和TimerSoure 和Runloop回調的觀察者集合.runloop每次循環(huán)都會指定一個模式,而且僅僅在這個模式下的Source會被執(zhí)行.
系統(tǒng)一共提供了以下幾種mode
NSDefaultRunLoopMode?(kCFRunLoopDefaultMode):默認的模式,大部分操作都在這個模式下,大部分時間都會使用這個mode
UITrackingRunLoopMode : 追蹤滑動情況下的模式
NSRunLoopCommonModes : 集合mode ,所有的runloop model 回調都會觸發(fā)
Input Sources
Input Sources 異步的處理線程的任務,Input Source一般分為兩種
一種為Port Sources,Port Source 一般由系統(tǒng)自動配置好的
一種為Custom Input Sources
Perform Selector Sources 是?Custom Input Sources的一種特殊情況
Timer Sources 同步處理任務,為了定時器的回調不受mode的影響,可以選擇將定時器加入NSRunLoopCommonModes
Run Loop Observers?
當runloop執(zhí)行的時候,runloop的觀察者會觸發(fā)通知,觸發(fā)通知的事件如下:
1.進入runloop循環(huán)
2.runloop將要處理定時器事件
3.runloop將要處理Input Source
4.runloop將要休眠
5.runloop被喚醒,但是此時還沒有開始處理喚醒runloop的事件
5.runloop退出
你可以添加runloop observe 來追蹤runloop處理事件的時機去處理額外的任務
配置并使用Runloop
在主線程中Runloop是默認啟動的,只有你創(chuàng)建了子線程,并在子線程中需要做處理InputSource事件,處理定時器,使用performSelector執(zhí)行延時方法,保持線程存在一段時間,才需要在子線程中啟動runloop.
使用[NSRunLoop currentRunLoop]就會自動創(chuàng)建runloop,你可以選擇有三種方法啟動runloop,
run方法無條件啟動,但是結果是無法結束runloop
runMode beforeDate 指定過期時間和mode啟動,也是無法結束runloop
runUntilDate 指定過期時間啟動,可以通過CFRunLoopStop結束runloop
監(jiān)聽runloop的狀態(tài):
//創(chuàng)建Observer上下文
CFRunLoopObserverContext context = {0,self,NULL,NULL,NULL};
//創(chuàng)建Observer
?CFRunLoopObserverRef obsever =? CFRunLoopObserverCreate(kCFAllocatorDefault, kCFRunLoopAllActivities, YES, 0, &RunloopObsever, &context);
//添加Observer
CFRunLoopAddObserver([[NSRunLoop currentRunLoop] getCFRunLoop], obsever, kCFRunLoopCommonModes);