RunLoop是一讓線程能隨時(shí)處理事件但不退出的機(jī)制。RunLoop 實(shí)際上是一個(gè)對(duì)象,這個(gè)對(duì)象管理了其需要處理的事件和消息,并提供了一個(gè)入口函數(shù)來執(zhí)行Event Loop 的邏輯。線程執(zhí)行了這個(gè)函數(shù)后,就會(huì)一直處于這個(gè)函數(shù)內(nèi)部 “接受消息->等待->處理” 的循環(huán)中,直到這個(gè)循環(huán)結(jié)束(比如傳入 quit 的消息),函數(shù)返回。讓線程在沒有處理消息時(shí)休眠以避免資源占用、在有消息到來時(shí)立刻被喚醒。

Runloop原理.png
do{
//通知將要處理timer和source
__CFRunLoopDoObservers(kCFRunLoopBeforeTimers);
__CFRunLoopDoObservers(kCFRunLoopBeforeSources);
__CFRunLoopDoBlocks();//處理非延遲的注線程調(diào)用
__CFRunLoopDoSource0();//處理UIEVent事件
//GCD dispatch main queue
CheckIfExistMessagesInMainDispatchQueue();
//即將進(jìn)入休眠
__CFRunLoopDoObservers(kCFRunLoopBeforeWaiting);
//等待內(nèi)核mach_msg事件
mach_port_t wakeupPort = SleepAndWaitForWakingUpPorts();
//Zzzz.....
//從等待中醒來
__CFRunLoopDoObservers(kCFRunLoopAfterWaiting);
//處理因timer的喚醒
if(wakeUpPort == timerPort)
__CFRunLoopDoTimers();
//處理異步方法喚醒,如dispatch_asyn
else if(wakeUpPort == mainDispatchQueuePort)
__CFRUNLOOP_IS_SERVICING_THE_MAIN_DISPATCH_QUEUE__()
//UI刷新,動(dòng)畫顯示
else
__CFRunLoopDoSource1();
//再次確保是否有同步的方法需要調(diào)用
__CFRunLoopDoBlocks();
}while(!stop && timeout);