RunLoop

简介: 简介什么是 RunLoop ?从字面意思看的话是运行循环、跑圈的意思;RunLoop 的基本作用是什么:保持程序的持续运行;处理 App 中的各种事件(比如触摸事件、定时器事件、Selector 事件);节省 CPU 资源,提高程序性能:...

简介

什么是 RunLoop ?

从字面意思看的话是运行循环、跑圈的意思;

RunLoop 的基本作用是什么:
  • 保持程序的持续运行;
  • 处理 App 中的各种事件(比如触摸事件、定时器事件、Selector 事件);
  • 节省 CPU 资源,提高程序性能:该做事时做事,该休息时休息;
如果没有RunLoop
int main(int argc, char * argv[])
{
    // 程序开始
    NSLog(@"execute main function");
    // 程序结束
    return 0;
}

没有 RunLoop 的情况下:第3行后程序就结束了;

如果有了RunLoop
int main(int argc, char * argv[]) 
{
    BOOL running = YES;
    do 
        {
            // 执行各种任务,处理各种事件
           // ......
        } while (running);
    return 0;
}

有 RunLoop 的情况下:由于 main 函数里面启动了个 RunLoop ,所以程序并不会马上退出,保持持续运行状态

main函数中的RunLoop
int main(int argc, char * argv[])
{
    @autoreleasepool
    {
        return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class]));
    }
}

第 5 行代码的 UIApplicationMain 函数内部就启动了一个 RunLoop 所以 UIApplicationMain 函数一直没有返回,保持了程序的持续运行。这个默认启动的 RunLoop 是跟主线程相关联的;

RunLoop对象

iOS 中哪些 API 来访问和使用 RunLoop?
  • Foundation
    NSRunLoop
  • Core Foundation
    CFRunLoopRef

NSRunLoop 和 CFRunLoopRef 都代表着 RunLoop 对象;

NSRunLoop 是基于 CFRunLoopRef 的一层 OC 包装,所以要了解RunLoop内部结构,需要多研究CFRunLoopRef层面的API(Core Foundation层面);

RunLoop资料
RunLoop与线程
  • 每条线程都有唯一的一个与之对应的 RunLoop 对象;
  • 主线程的 RunLoop 已经自动创建好了,子线程的 RunLoop 需要主动创建;
  • RunLoop 在第一次获取时创建,在线程结束时销毁;
获得 RunLoop 对象
  • Foundation
// 获得当前线程的RunLoop对象
[NSRunLoop currentRunLoop]; 
// 获得主线程的RunLoop对象
[NSRunLoop mainRunLoop]; 
  • Core Foundation
// 获得当前线程的RunLoop对象
CFRunLoopGetCurrent(); 
 // 获得主线程的RunLoop对象
CFRunLoopGetMain();

RunLoop相关类

Core Foundation 中有几个关于RunLoop的类?

Core Foundation 中有5个关于RunLoop的类;

  • CFRunLoopRef
  • CFRunLoopModeRef
  • CFRunLoopSourceRef
  • CFRunLoopTimerRef
  • CFRunLoopObserverRef
img_58ecbdecc95fed00607db45da77ee57a.png
RunLoop
CFRunLoopModeRef
  • CFRunLoopModeRef 代表 RunLoop 的运行模式;
  • 一个 RunLoop 包含若干个 Mode,每个 Mode 又包含若干个Source/Observer/Timer;
  • 每次 RunLoop 启动时,只能指定其中一个 Mode,这个 Mode 被称作 CurrentMode;
  • 如果需要切换 Mode,只能退出 Loop,再重新指定一个 Mode 进入
  • 这样做主要是为了分隔开不同组的 Source/Observer/Timer,让其互不影响;
RunLoop 中有几种 Mode?

系统默认注册了 5 种 Mode;

  • kCFRunLoopDefaultMode:App 的默认 Mode ,通常主线程是在这个 Mode 下运行;
  • UITrackingRunLoopMode:界面跟踪 Mode,用于 ScrollView 追踪触摸滑动,保证界面滑动时不受其他 Mode 影响;
  • UIInitializationRunLoopMode: 在刚启动 App 时第进入的第一个 Mode ,启动完成后就不再使用;
  • GSEventReceiveRunLoopMode: 接受系统事件的内部 Mode ,通常用不到;
  • kCFRunLoopCommonModes: 这是一个占位用的 Mode ,不是一种真正的Mode;
CFRunLoopSourceRef

CFRunLoopSourceRef 是事件源(输入源)

  • 按照 Apple 官方文档 Sources 的分类:
    Port-Based Sources
    Custom Input Sources
    Cocoa Perform Selector Sources

  • 按照函数调用栈 Sources 的分类:
    Source0:非基于 Port;
    Source1:基于 Port,通过内核和其他线程通信,接受,分发系统事件;

CFRunLoopTimerRef

CFRunLoopTimerRef 是基于时间的触发器;
基本上说的就是 NSTimer;

CFRunLoopObserverRef

CFRunLoopObserverRef 是观察者,能够监听 RunLoop 的状态改变;

可以监听的时间点有以下几个

typedef CF_OPTIONS(CFOptionFlags, CFRunLoopActivity) 
{
    // 即将进入 RunLoop
    kCFRunLoopEntry = (1UL << 0) = 1,
    // 即将处理 Timer
    kCFRunLoopBeforeTimers = (1UL << 1) = 2,
    // 即将处理 Source
    kCFRunLoopBeforeSources = (1UL << 2) = 4,
    // 即将进入 睡眠
    kCFRunLoopBeforeWaiting = (1UL << 5) = 32,
    // 刚从 睡眠 中 唤醒
    kCFRunLoopAfterWaiting = (1UL << 6) = 64,
    // 即将退出 RunLoop
    kCFRunLoopExit = (1UL << 7) = 128,
    // 所有活动
    kCFRunLoopAllActivities = 0x0FFFFFFFU
};

RunLoop 处理逻辑

官方版
img_f393cb97bdc4cc0cffe669d74cce93f6.png
官方版 RunLoop 处理逻辑
img_454b1e55831f9a90e84978f53f816343.png
官方版 RunLoop 处理逻辑
网友整理版
img_da20a20dc90e6625643f9d7c35f0da7a.png
网友整理版 RunLoop 处理逻辑

RunLoop 应用

  • NSTimer
  • ImageView显示
  • PerformSelector
  • 常驻线程
  • 自动释放池
目录
相关文章
|
机器学习/深度学习 人工智能 自然语言处理
图解机器学习 | GBDT模型详解
GBDT是一种迭代的决策树算法,将决策树与集成思想进行了有效的结合。本文讲解GBDT算法的Boosting核心思想、训练过程、优缺点、与随机森林的对比、以及Python代码实现。
9530 2
图解机器学习 | GBDT模型详解
|
7月前
|
算法 搜索推荐
刷视频背后的逻辑:数据驱动的社交平台发展趋势
刷视频背后的逻辑:数据驱动的社交平台发展趋势
187 5
|
10月前
|
JSON JavaScript 前端开发
HarmonyOS NEXT实战:接入和使用axios
HarmonyOS Next 实战中,使用 Axios 可实现高效网络请求。Axios 是基于 Promise 的库,支持 GET、POST 等方法,并具备拦截器、自动 JSON 转换等功能。适配 OpenHarmony 后,仍保留其原有特性。需安装 @ohos/axios 并配置网络权限,可创建工具类统一管理请求与响应。
515 0
|
人工智能 Linux API
Omnitool:开发者桌面革命!开源神器一键整合ChatGPT+Stable Diffusion等主流AI平台,本地运行不联网
Omnitool 是一款开源的 AI 桌面环境,支持本地运行,提供统一交互界面,快速接入 OpenAI、Stable Diffusion、Hugging Face 等主流 AI 平台,具备高度扩展性。
1467 94
Omnitool:开发者桌面革命!开源神器一键整合ChatGPT+Stable Diffusion等主流AI平台,本地运行不联网
|
机器学习/深度学习 算法 测试技术
深度学习环境搭建笔记(二):mmdetection-CPU安装和训练
本文是关于如何搭建深度学习环境,特别是使用mmdetection进行CPU安装和训练的详细指南。包括安装Anaconda、创建虚拟环境、安装PyTorch、mmcv-full和mmdetection,以及测试环境和训练目标检测模型的步骤。还提供了数据集准备、检查和网络训练的详细说明。
1127 5
深度学习环境搭建笔记(二):mmdetection-CPU安装和训练
|
存储 边缘计算 数据处理
边缘计算和云计算的区别
边缘计算和云计算是两种不同的计算范式。云计算通过互联网提供集中式处理、可扩展性和成本效益等优势,而边缘计算则在数据源附近进行分布式处理,具有低延迟、带宽优化和本地化决策等优点。两者在响应时间、网络带宽和安全性方面有显著区别,常互补使用以满足不同应用场景的需求。
1787 3
|
存储 机器学习/深度学习 人工智能
数据结构学习笔记——图的存储结构(邻接矩阵和邻接表)
数据结构学习笔记——图的存储结构(邻接矩阵和邻接表)
数据结构学习笔记——图的存储结构(邻接矩阵和邻接表)
|
数据采集 机器学习/深度学习 数据可视化
完整的Python数据分析流程案例解析-数据科学项目实战
【7月更文挑战第5天】这是一个Python数据分析项目的概览,涵盖了从CSV数据加载到模型评估的步骤:获取数据、预处理(处理缺失值和异常值、转换数据)、数据探索(可视化和统计分析)、模型选择(线性回归)、训练与评估、优化,以及结果的可视化和解释。此流程展示了理论与实践的结合在解决实际问题中的应用。
715 1
|
消息中间件 JavaScript 小程序
MQTT常见问题之mqtt通过token连接成功之后立马就断掉如何解决
MQTT(Message Queuing Telemetry Transport)是一个轻量级的、基于发布/订阅模式的消息协议,广泛用于物联网(IoT)中设备间的通信。以下是MQTT使用过程中可能遇到的一些常见问题及其答案的汇总:
|
前端开发 Java 关系型数据库
xxl-job 登入功能集成 OIDC 统一认证
xxl-job 是一款 java 开发的、开源的分布式任务调度系统,自带了登录认证功能,不支持对接、扩展 LDAP 、OIDC 等标准认证系统,考虑到单独维护 xxl-job 自有的用户系统不方便,以及存在人员离职、调岗、权限变动等需要及时调整用户权限的情况,需要接入公司统一的 OIDC 认证系统
2385 0