午夜剧场伦理_日本一道高清_国产又黄又硬_91黄色网战_女同久久另类69精品国产_妹妹的朋友在线

您的位置:首頁(yè)技術(shù)文章
文章詳情頁(yè)

分析IOS RunLoop的事件循環(huán)機(jī)制

瀏覽:117日期:2022-09-16 15:44:18

在RunLoop啟動(dòng)之后會(huì)發(fā)送一個(gè)通知,來(lái)告知觀察者

將要處理Timer/Source0事件這樣一個(gè)通知的發(fā)送

處理Source0事件

如果有Source1要處理,這時(shí)會(huì)通過(guò)一個(gè)go to語(yǔ)句的實(shí)現(xiàn)來(lái)進(jìn)行代碼邏輯的跳轉(zhuǎn),處理喚醒是收到的消息

如果沒(méi)有Source1要處理,線程就將要休眠,同時(shí)發(fā)送一個(gè)通知,告訴觀察者

然后線程進(jìn)入一個(gè)用戶態(tài)到內(nèi)核態(tài)的切換,休眠,然后等待喚醒,喚醒的條件大約包括三種:

1、Source1

2、Timer事件

3、外部手動(dòng)喚醒

線程剛被喚醒之后也要發(fā)送一個(gè)通知告訴觀察者,然后處理喚醒時(shí)收到的消息

回到將要處理Timer/Source0事件這樣一個(gè)通知的發(fā)送

然后再次進(jìn)行上面步驟,這就是一個(gè)RunLoop的事件循環(huán)機(jī)制

內(nèi)部代碼邏輯整理如下:

/// 用DefaultMode啟動(dòng)void CFRunLoopRun(void) { CFRunLoopRunSpecific(CFRunLoopGetCurrent(), kCFRunLoopDefaultMode, 1.0e10, false);} /// 用指定的Mode啟動(dòng),允許設(shè)置RunLoop超時(shí)時(shí)間int CFRunLoopRunInMode(CFStringRef modeName, CFTimeInterval seconds, Boolean stopAfterHandle) { return CFRunLoopRunSpecific(CFRunLoopGetCurrent(), modeName, seconds, returnAfterSourceHandled);} /// RunLoop的實(shí)現(xiàn)int CFRunLoopRunSpecific(runloop, modeName, seconds, stopAfterHandle) {/// 首先根據(jù)modeName找到對(duì)應(yīng)mode CFRunLoopModeRef currentMode = __CFRunLoopFindMode(runloop, modeName, false); /// 如果mode里沒(méi)有source/timer/observer, 直接返回。 if (__CFRunLoopModeIsEmpty(currentMode)) return;/// 1. 通知 Observers: RunLoop 即將進(jìn)入 loop。 __CFRunLoopDoObservers(runloop, currentMode, kCFRunLoopEntry);/// 內(nèi)部函數(shù),進(jìn)入loop __CFRunLoopRun(runloop, currentMode, seconds, returnAfterSourceHandled) {Boolean sourceHandledThisLoop = NO;int retVal = 0;do { /// 2. 通知 Observers: RunLoop 即將觸發(fā) Timer 回調(diào)。 __CFRunLoopDoObservers(runloop, currentMode, kCFRunLoopBeforeTimers); /// 3. 通知 Observers: RunLoop 即將觸發(fā) Source0 (非port) 回調(diào)。 __CFRunLoopDoObservers(runloop, currentMode, kCFRunLoopBeforeSources); /// 執(zhí)行被加入的block __CFRunLoopDoBlocks(runloop, currentMode);/// 4. RunLoop 觸發(fā) Source0 (非port) 回調(diào)。 sourceHandledThisLoop = __CFRunLoopDoSources0(runloop, currentMode, stopAfterHandle); /// 執(zhí)行被加入的block __CFRunLoopDoBlocks(runloop, currentMode); /// 5. 如果有 Source1 (基于port) 處于 ready 狀態(tài),直接處理這個(gè) Source1 然后跳轉(zhuǎn)去處理消息。 if (__Source0DidDispatchPortLastTime) {Boolean hasMsg = __CFRunLoopServiceMachPort(dispatchPort, &msg)if (hasMsg) goto handle_msg; }/// 通知 Observers: RunLoop 的線程即將進(jìn)入休眠(sleep)。 if (!sourceHandledThisLoop) {__CFRunLoopDoObservers(runloop, currentMode, kCFRunLoopBeforeWaiting); }/// 7. 調(diào)用 mach_msg 等待接受 mach_port 的消息。線程將進(jìn)入休眠, 直到被下面某一個(gè)事件喚醒。 /// • 一個(gè)基于 port 的Source 的事件。 /// • 一個(gè) Timer 到時(shí)間了 /// • RunLoop 自身的超時(shí)時(shí)間到了 /// • 被其他什么調(diào)用者手動(dòng)喚醒 __CFRunLoopServiceMachPort(waitSet, &msg, sizeof(msg_buffer), &livePort) {mach_msg(msg, MACH_RCV_MSG, port); // thread wait for receive msg } /// 8. 通知 Observers: RunLoop 的線程剛剛被喚醒了。 __CFRunLoopDoObservers(runloop, currentMode, kCFRunLoopAfterWaiting);/// 收到消息,處理消息。 handle_msg: /// 9.1 如果一個(gè) Timer 到時(shí)間了,觸發(fā)這個(gè)Timer的回調(diào)。 if (msg_is_timer) {__CFRunLoopDoTimers(runloop, currentMode, mach_absolute_time()) } /// 9.2 如果有dispatch到main_queue的block,執(zhí)行block。 else if (msg_is_dispatch) {__CFRUNLOOP_IS_SERVICING_THE_MAIN_DISPATCH_QUEUE__(msg); } /// 9.3 如果一個(gè) Source1 (基于port) 發(fā)出事件了,處理這個(gè)事件 else {CFRunLoopSourceRef source1 = __CFRunLoopModeFindSourceForMachPort(runloop, currentMode, livePort);sourceHandledThisLoop = __CFRunLoopDoSource1(runloop, currentMode, source1, msg);if (sourceHandledThisLoop) { mach_msg(reply, MACH_SEND_MSG, reply);} }/// 執(zhí)行加入到Loop的block __CFRunLoopDoBlocks(runloop, currentMode); if (sourceHandledThisLoop && stopAfterHandle) {/// 進(jìn)入loop時(shí)參數(shù)說(shuō)處理完事件就返回。retVal = kCFRunLoopRunHandledSource; } else if (timeout) {/// 超出傳入?yún)?shù)標(biāo)記的超時(shí)時(shí)間了retVal = kCFRunLoopRunTimedOut; } else if (__CFRunLoopIsStopped(runloop)) {/// 被外部調(diào)用者強(qiáng)制停止了retVal = kCFRunLoopRunStopped; } else if (__CFRunLoopModeIsEmpty(runloop, currentMode)) {/// source/timer/observer一個(gè)都沒(méi)有了retVal = kCFRunLoopRunFinished; }/// 如果沒(méi)超時(shí),mode里沒(méi)空,loop也沒(méi)被停止,那繼續(xù)loop。} while (retVal == 0); }/// 10. 通知 Observers: RunLoop 即將退出。 __CFRunLoopDoObservers(rl, currentMode, kCFRunLoopExit);}

可以看到,實(shí)際上 RunLoop 就是這樣一個(gè)函數(shù),其內(nèi)部是一個(gè)do-while循環(huán)。當(dāng)你調(diào)用CFRunLoopRun()時(shí),線程就會(huì)一直停留在這個(gè)循環(huán)里;直到超時(shí)或被手動(dòng)停止,該函數(shù)才會(huì)返回

有一個(gè)這樣的問(wèn)題:當(dāng)我們點(diǎn)擊一個(gè)app,從我們點(diǎn)擊到程序啟動(dòng)、程序運(yùn)行再到程序殺死這個(gè)過(guò)程,系統(tǒng)都發(fā)生了什么呢?

實(shí)際上當(dāng)我們調(diào)用了main函數(shù)之后,會(huì)調(diào)用UIApplicationMain函數(shù),在這個(gè)函數(shù)內(nèi)部會(huì)啟動(dòng)主線程的RunLoop,然后經(jīng)過(guò)一系列的處理,最終主線程的RunLoop會(huì)處于一個(gè)休眠狀態(tài),然后我們此時(shí)如果點(diǎn)擊一下屏幕,會(huì)轉(zhuǎn)化成一個(gè)Source1來(lái)讓我們的主線程喚醒,然后當(dāng)我們殺死程序時(shí),會(huì)調(diào)用RunLoop的退出,同時(shí)發(fā)送通知告訴觀察者

找到一張總結(jié)圖幫助記憶:

分析IOS RunLoop的事件循環(huán)機(jī)制

以上就是分析IOS RunLoop的事件循環(huán)機(jī)制的詳細(xì)內(nèi)容,更多關(guān)于IOS RunLoop的事件循環(huán)機(jī)制的資料請(qǐng)關(guān)注好吧啦網(wǎng)其它相關(guān)文章!

標(biāo)簽: IOS
相關(guān)文章:
主站蜘蛛池模板: 麻豆视频免费在线播放 | www.中文字幕在线观看 | 黄色成年视频 | jk在线观看 | 亚欧精品在线 | 国产一区二区久久久 | av国产免费 | 啪啪免费网 | 五月婷婷久久综合 | 成人在线三级 | 国产91高清| 动漫av网| 国产三级小视频 | 亚洲成人另类 | 精品亚洲国产成av人片传媒 | 91精品国产成人 | 日韩欧美一级视频 | 国产精品18在线 | 欧美精品99 | 国产高清av | 美国一级黄色录像 | 在线精品亚洲欧美日韩国产 | 91精品国产综合久久久蜜臀粉嫩 | 日韩中文在线视频 | 欧美亚洲精品在线 | 免费成人深夜在线观看 | 色av一区二区 | a毛片在线 | 亚洲天堂手机在线 | 久色免费视频 | 麻豆国产一区二区三区四区 | 日韩欧美国产高清 | 亚洲欧美另类在线观看 | 久操青青 | 欧美日韩一区二区三 | 久久精品18| 青草精品 | 日本大片在线 | 欧美成人一区二区三区片免费 | 日韩精品中文字幕在线观看 | 欧美精品123 |