iOS RunLoop 介绍

💡 原文中文,约19400字,阅读约需47分钟。
📝

内容提要

RunLoop是用于管理事件源和线程的消息循环,可以保持应用程序活动并节省能耗。RunLoop的实现依赖于底层操作系统的机制,通过mach port实现线程的休眠和唤醒。RunLoop由运行循环、运行模式、事件源、定时器和观察者组成。可以使用RunLoop实现线程保活和异步更新UI等功能。

🔎

延伸解读

RunLoop 与线程保活:原理与实现

文章指出,子线程的 RunLoop 需要手动创建并启动,且必须至少添加一个事件源(如 Port 或 Source),否则 RunLoop 会立即退出。通过添加一个空的 Mach Port,可以让 RunLoop 在没有实际事件时保持休眠,从而实现线程保活。这解释了为什么在子线程中使用 RunLoop 时,必须调用 run 方法并确保有事件源存在。

RunLoop 模式切换对定时器的影响

文章通过面试题说明,当滑动 UITableView 时,主线程 RunLoop 会从 NSDefaultRunLoopMode 切换到 UITrackingRunLoopMode,导致在默认模式下注册的 NSTimer 暂停触发。解决方法是将定时器添加到 NSRunLoopCommonModes,这样定时器在两种模式下都能运行。这提醒开发者注意模式切换对定时任务的影响。

RunLoop 观察者与自动释放池的协作

文章提到,系统在主线程 RunLoop 中注册了两个观察者,分别在 RunLoop 进入和休眠/退出时管理自动释放池的创建与释放。第一个观察者在 Entry 时创建池,第二个在 BeforeWaiting 和 Exit 时释放并重建池。这保证了主线程事件回调中的临时对象能及时释放,开发者通常无需手动创建自动释放池。

RunLoop 在异步 UI 更新中的应用

文章指出,在子线程请求数据后,若直接切回主线程更新 UI,可能会打断用户的滑动操作,因为主线程 RunLoop 正处于 UITrackingRunLoopMode。通过 performSelectorOnMainThread:withObject:waitUntilDone:modes: 指定 NSDefaultRunLoopMode,可以将 UI 更新推迟到滑动结束后执行,从而避免影响用户体验。

❓

Q&A

RunLoop的主要功能是什么?

RunLoop用于管理事件源和线程的消息循环,保持应用程序活动并节省能耗。

如何在子线程中创建和启动RunLoop?

子线程需要手动创建并启动RunLoop,可以通过调用run方法来实现。

RunLoop的运行模式有哪些?

RunLoop的运行模式包括默认模式、通用模式和自定义模式。

RunLoop如何处理定时器事件?

RunLoop通过定时器在注册的时间到达时唤醒线程来执行定时器的回调。

RunLoop中的观察者有什么作用?

观察者用于监视RunLoop状态变化,能够在状态变化时执行回调。

如何使用RunLoop实现线程保活?

在当前线程开启一个RunLoop,并向其中添加一个Port/Source以维持事件循环。

🏷️

标签

➡️

继续阅读