? Source1 :基于mach_Port的,來自系統(tǒng)內(nèi)核或者其他進程或線程的事件,可以主動喚醒休眠中的RunLoop(iOS里進程間通信開發(fā)過程中我們一般不主動使用)。mach_port大家就理解成進程間相互發(fā)送消息的一種機制就好, 比如屏幕點擊, 網(wǎng)絡(luò)數(shù)據(jù)的傳輸都會觸發(fā)sourse1。
蘋果創(chuàng)建用來接受系統(tǒng)發(fā)出事件,當(dāng)手機發(fā)生一個觸摸,搖晃或鎖屏等系統(tǒng),這時候系統(tǒng)會發(fā)送一個事件到app進程(進程通信),這也就是為什么叫基于port傳遞source1的原因,port就是進程端口嘛,該事件可以激活進程里線程的runloop,比如你點擊一下app的按鈕或屏幕,runloop就醒過來處理觸摸事件,你可以做個實驗,在主線程的runloop中添加一個CFRunLoopObserverRef,用switch輸出runloop6個狀態(tài),這時候你每點擊一次屏幕,他就會輸出Runloop六個狀態(tài),然后進入休眠。
? Source0 :非基于Port的 處理事件,什么叫非基于Port的呢?就是說你這個消息不是其他進程或者內(nèi)核直接發(fā)送給你的。一般是APP內(nèi)部的事件, 比如hitTest:withEvent的處理, performSelectors的事件.
執(zhí)行performSelectors方法,假如你在主線程performSelectors一個任務(wù)到子線程,這時候就是在代碼中發(fā)送事件到子線程的runloop,這時候如果子線程開啟了runloop就會執(zhí)行該任務(wù),注意該performSelector方法只有在你子線程開啟runloop才能執(zhí)行,如果你沒有在子線程中開啟runloop,那么該操作會無法執(zhí)行并崩潰。
簡單舉個例子:一個APP在前臺靜止著,此時,用戶用手指點擊了一下APP界面,那么過程就是下面這樣的:
我們觸摸屏幕,先摸到硬件(屏幕),屏幕表面的事件會被IOKit先包裝成Event,通過mach_Port傳給正在活躍的APP , Event先告訴source1(mach_port),source1喚醒RunLoop, 然后將事件Event分發(fā)給source0,然后由source0來處理。
如果沒有事件,也沒有timer,則runloop就會睡眠, 如果有,則runloop就會被喚醒,然后跑一圈。