电脑知识|欧美黑人一区二区三区|软件|欧美黑人一级爽快片淫片高清|系统|欧美黑人狂野猛交老妇|数据库|服务器|编程开发|网络运营|知识问答|技术教程文章 - 好吧啦网

您的位置:首頁技術文章
文章詳情頁

分析IOS RunLoop的事件循環機制

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

在RunLoop啟動之后會發送一個通知,來告知觀察者

將要處理Timer/Source0事件這樣一個通知的發送

處理Source0事件

如果有Source1要處理,這時會通過一個go to語句的實現來進行代碼邏輯的跳轉,處理喚醒是收到的消息

如果沒有Source1要處理,線程就將要休眠,同時發送一個通知,告訴觀察者

然后線程進入一個用戶態到內核態的切換,休眠,然后等待喚醒,喚醒的條件大約包括三種:

1、Source1

2、Timer事件

3、外部手動喚醒

線程剛被喚醒之后也要發送一個通知告訴觀察者,然后處理喚醒時收到的消息

回到將要處理Timer/Source0事件這樣一個通知的發送

然后再次進行上面步驟,這就是一個RunLoop的事件循環機制

內部代碼邏輯整理如下:

/// 用DefaultMode啟動void CFRunLoopRun(void) { CFRunLoopRunSpecific(CFRunLoopGetCurrent(), kCFRunLoopDefaultMode, 1.0e10, false);} /// 用指定的Mode啟動,允許設置RunLoop超時時間int CFRunLoopRunInMode(CFStringRef modeName, CFTimeInterval seconds, Boolean stopAfterHandle) { return CFRunLoopRunSpecific(CFRunLoopGetCurrent(), modeName, seconds, returnAfterSourceHandled);} /// RunLoop的實現int CFRunLoopRunSpecific(runloop, modeName, seconds, stopAfterHandle) {/// 首先根據modeName找到對應mode CFRunLoopModeRef currentMode = __CFRunLoopFindMode(runloop, modeName, false); /// 如果mode里沒有source/timer/observer, 直接返回。 if (__CFRunLoopModeIsEmpty(currentMode)) return;/// 1. 通知 Observers: RunLoop 即將進入 loop。 __CFRunLoopDoObservers(runloop, currentMode, kCFRunLoopEntry);/// 內部函數,進入loop __CFRunLoopRun(runloop, currentMode, seconds, returnAfterSourceHandled) {Boolean sourceHandledThisLoop = NO;int retVal = 0;do { /// 2. 通知 Observers: RunLoop 即將觸發 Timer 回調。 __CFRunLoopDoObservers(runloop, currentMode, kCFRunLoopBeforeTimers); /// 3. 通知 Observers: RunLoop 即將觸發 Source0 (非port) 回調。 __CFRunLoopDoObservers(runloop, currentMode, kCFRunLoopBeforeSources); /// 執行被加入的block __CFRunLoopDoBlocks(runloop, currentMode);/// 4. RunLoop 觸發 Source0 (非port) 回調。 sourceHandledThisLoop = __CFRunLoopDoSources0(runloop, currentMode, stopAfterHandle); /// 執行被加入的block __CFRunLoopDoBlocks(runloop, currentMode); /// 5. 如果有 Source1 (基于port) 處于 ready 狀態,直接處理這個 Source1 然后跳轉去處理消息。 if (__Source0DidDispatchPortLastTime) {Boolean hasMsg = __CFRunLoopServiceMachPort(dispatchPort, &msg)if (hasMsg) goto handle_msg; }/// 通知 Observers: RunLoop 的線程即將進入休眠(sleep)。 if (!sourceHandledThisLoop) {__CFRunLoopDoObservers(runloop, currentMode, kCFRunLoopBeforeWaiting); }/// 7. 調用 mach_msg 等待接受 mach_port 的消息。線程將進入休眠, 直到被下面某一個事件喚醒。 /// • 一個基于 port 的Source 的事件。 /// • 一個 Timer 到時間了 /// • RunLoop 自身的超時時間到了 /// • 被其他什么調用者手動喚醒 __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 如果一個 Timer 到時間了,觸發這個Timer的回調。 if (msg_is_timer) {__CFRunLoopDoTimers(runloop, currentMode, mach_absolute_time()) } /// 9.2 如果有dispatch到main_queue的block,執行block。 else if (msg_is_dispatch) {__CFRUNLOOP_IS_SERVICING_THE_MAIN_DISPATCH_QUEUE__(msg); } /// 9.3 如果一個 Source1 (基于port) 發出事件了,處理這個事件 else {CFRunLoopSourceRef source1 = __CFRunLoopModeFindSourceForMachPort(runloop, currentMode, livePort);sourceHandledThisLoop = __CFRunLoopDoSource1(runloop, currentMode, source1, msg);if (sourceHandledThisLoop) { mach_msg(reply, MACH_SEND_MSG, reply);} }/// 執行加入到Loop的block __CFRunLoopDoBlocks(runloop, currentMode); if (sourceHandledThisLoop && stopAfterHandle) {/// 進入loop時參數說處理完事件就返回。retVal = kCFRunLoopRunHandledSource; } else if (timeout) {/// 超出傳入參數標記的超時時間了retVal = kCFRunLoopRunTimedOut; } else if (__CFRunLoopIsStopped(runloop)) {/// 被外部調用者強制停止了retVal = kCFRunLoopRunStopped; } else if (__CFRunLoopModeIsEmpty(runloop, currentMode)) {/// source/timer/observer一個都沒有了retVal = kCFRunLoopRunFinished; }/// 如果沒超時,mode里沒空,loop也沒被停止,那繼續loop。} while (retVal == 0); }/// 10. 通知 Observers: RunLoop 即將退出。 __CFRunLoopDoObservers(rl, currentMode, kCFRunLoopExit);}

可以看到,實際上 RunLoop 就是這樣一個函數,其內部是一個do-while循環。當你調用CFRunLoopRun()時,線程就會一直停留在這個循環里;直到超時或被手動停止,該函數才會返回

有一個這樣的問題:當我們點擊一個app,從我們點擊到程序啟動、程序運行再到程序殺死這個過程,系統都發生了什么呢?

實際上當我們調用了main函數之后,會調用UIApplicationMain函數,在這個函數內部會啟動主線程的RunLoop,然后經過一系列的處理,最終主線程的RunLoop會處于一個休眠狀態,然后我們此時如果點擊一下屏幕,會轉化成一個Source1來讓我們的主線程喚醒,然后當我們殺死程序時,會調用RunLoop的退出,同時發送通知告訴觀察者

找到一張總結圖幫助記憶:

分析IOS RunLoop的事件循環機制

以上就是分析IOS RunLoop的事件循環機制的詳細內容,更多關于IOS RunLoop的事件循環機制的資料請關注好吧啦網其它相關文章!

標簽: IOS
相關文章:
主站蜘蛛池模板: 郑州大巴车出租|中巴车租赁|旅游大巴租车|包车|郑州旅游大巴车租赁有限公司 | 专业音响设备_舞台音响设备_会议音响工程-首选深圳一禾科技 | 凝胶成像系统(wb成像系统)百科-上海嘉鹏 | 派克防爆伺服电机品牌|国产防爆伺服电机|高低温伺服电机|杭州摩森机电科技有限公司 | 上海防爆真空干燥箱-上海防爆冷库-上海防爆冷柜?-上海浦下防爆设备厂家? | 东莞螺杆空压机_永磁变频空压机_节能空压机_空压机工厂批发_深圳螺杆空压机_广州螺杆空压机_东莞空压机_空压机批发_东莞空压机工厂批发_东莞市文颖设备科技有限公司 | 百度关键词优化_网站优化_SEO价格 - 云无限好排名 | 海鲜池-专注海鲜鱼缸、移动海鲜缸、饭店鱼缸设计定做-日晟水族厂家 | 塑料撕碎机_编织袋撕碎机_废纸撕碎机_生活垃圾撕碎机_废铁破碎机_河南鑫世昌机械制造有限公司 | 强效碱性清洗剂-实验室中性清洗剂-食品级高纯氮气发生器-上海润榕科学器材有限公司 | 菲希尔X射线测厚仪-菲希尔库伦法测厚仪-无锡骏展仪器有限责任公司 | RFID电子标签厂家-上海尼太普电子有限公司| 铆钉机|旋铆机|东莞旋铆机厂家|鸿佰专业生产气压/油压/自动铆钉机 | 多物理场仿真软件_电磁仿真软件_EDA多物理场仿真软件 - 裕兴木兰 | 卓能JOINTLEAN端子连接器厂家-专业提供PCB接线端子|轨道式端子|重载连接器|欧式连接器等电气连接产品和服务 | 东莞动力锂电池保护板_BMS智能软件保护板_锂电池主动均衡保护板-东莞市倡芯电子科技有限公司 | led太阳能路灯厂家价格_风光互补庭院灯_农村市政工程路灯-中山华可路灯品牌 | 石膏基自流平砂浆厂家-高强石膏基保温隔声自流平-轻质抹灰石膏粉砂浆批发-永康市汇利建设有限公司 | 重庆钣金加工厂家首页-专业定做监控电视墙_操作台 | 广东佛电电器有限公司|防雷开关|故障电弧断路器|智能量测断路器 广东西屋电气有限公司-广东西屋电气有限公司 | 超声波成孔成槽质量检测仪-压浆机-桥梁预应力智能张拉设备-上海硕冠检测设备有限公司 | 生物除臭剂-除味剂-植物-污水除臭剂厂家-携葵环保有限公司 | 济南ISO9000认证咨询代理公司,ISO9001认证,CMA实验室认证,ISO/TS16949认证,服务体系认证,资产管理体系认证,SC食品生产许可证- 济南创远企业管理咨询有限公司 郑州电线电缆厂家-防火|低压|低烟无卤电缆-河南明星电缆 | 福建成考网-福建成人高考网 | 丝印油墨_水性油墨_环保油墨油漆厂家_37国际化工 | 温湿度记录纸_圆盘_横河记录纸|霍尼韦尔记录仪-广州汤米斯机电设备有限公司 | b2b网站大全,b2b网站排名,找b2b网站就上地球网 | PE一体化污水处理设备_地埋式生活污水净化槽定制厂家-岩康塑业 | 空冷器|空气冷却器|空水冷却器-无锡赛迪森机械有限公司[官网] | 冷却塔减速机器_冷却塔皮带箱维修厂家_凉水塔风机电机更换-广东康明冷却塔厂家 | 玻璃钢格栅盖板|玻璃钢盖板|玻璃钢格栅板|树篦子-长沙川皖玻璃钢制品有限公司 | 酒水灌装机-白酒灌装机-酒精果酒酱油醋灌装设备_青州惠联灌装机械 | 可程式恒温恒湿试验箱|恒温恒湿箱|恒温恒湿试验箱|恒温恒湿老化试验箱|高低温试验箱价格报价-广东德瑞检测设备有限公司 | 沈飞防静电地板__机房地板-深圳市沈飞防静电设备有限公司 | 密集柜_档案密集柜_智能密集架_密集柜厂家_密集架价格-智英伟业 密集架-密集柜厂家-智能档案密集架-自动选层柜订做-河北风顺金属制品有限公司 | 上海风淋室_上海风淋室厂家_上海风淋室价格_上海伯淋 | 卫浴散热器,卫浴暖气片,卫生间背篓暖气片,华圣格浴室暖气片 | 厦门ISO认证|厦门ISO9001认证|厦门ISO14001认证|厦门ISO45001认证-艾索咨询专注ISO认证行业 | 自动部分收集器,进口无油隔膜真空泵,SPME固相微萃取头-上海楚定分析仪器有限公司 | 精密模具制造,注塑加工,吹塑和吹瓶加工,EPS泡沫包装生产 - 济南兴田塑胶有限公司 | 螺杆真空泵_耐腐蚀螺杆真空泵_水环真空泵_真空机组_烟台真空泵-烟台斯凯威真空 |