The Run Loop Sequence of Eventsoop
Each time you run it, your thread’s run loop processes pending events and generates notifications for any attached observers. The order in which it does this is very specific and is as follows:this
1, Notify observers that the run loop has been entered.spa
2, Notify observers that any ready timers are about to fire.rest
3, Notify observers that any input sources that are not port based are about to fire.server
4, Fire any non-port-based input sources that are ready to fire.隊列
5, If a port-based input source is ready and waiting to fire, process the event immediately. Go to step 9.事件
6, Notify observers that the thread is about to sleep. ci
7, Put the thread to sleep until one of the following events occurs:rem
An event arrives for a port-based input source.input
A timer fires.
The timeout value set for the run loop expires.
The run loop is explicitly woken up.
8, Notify observers that the thread just woke up.
9,Process the pending event.
If a user-defined timer fired, process the timer event and restart the loop. Go to step 2.
If an input source fired, deliver the event.
If the run loop was explicitly woken up but has not yet timed out, restart the loop. Go to step 2.
10, Notify observers that the run loop has exited.
從 步驟2 到 步驟9 稱爲 一個 loop,
另外注意fire source 和 deliver event的區別:
fire xx source 的意思是將該 source 加入監聽隊列,由於能夠隨時add 和 remove source ,因此每次loop 都要處理;
deliver event 就是調度、處理source 觸發的event。
從整個過程能夠看出,
Port-based input source 事件優先級是最高的,port-based source 註冊後會立刻執行,可是port event 並不屏蔽其餘事件,處理完 port event 能夠在同一個loop中繼續處理其它事件(Timer 、 custom、 selector)
Timer事件比較特殊, 從第九步能夠看出每次 系統timer(non-user-defined timer) 事件觸發後,會致使loop重新開始,其他事件(custom、 selector)只能在新的loop獲得處理機會;
Timer 事件 和 port 事件能夠喚醒 休眠的runloop, 可是其餘input source 事件不具備這個功能, 因此在本身寫的input source 執行完 CFRunLoopSourceSignal(runLoopSource) 發消息操做後, 還要執行 CFRunLoopWakeUp(runloop) 把 runloop 喚醒, 這樣消息才能獲得及時處理
runMode:beforeDate方法執行一次,內部可能發生 1次 或 屢次loop
除了Port-based event 和 Timer event, RunLoop 的 runMode:beforeDate 方法每次處理完一個 input source 事件(包括custom 、selector)或者time out就會返回。