主线程是如何切换runloop的探究

iOS SDK详解之Runloop 原创Blog,转载请注明出处 http://blog.youkuaiyun.com/hello_hwc?viewmode=list 我的stackoverflow前言:Runloop多线程开发的中的一个概念,当然也可以向Runloop中提交一些任务,监听一些事件。属于多线程编程的一部分,合理的使用Runloop对App的性能提高有很大帮助。关于Runloop 的官方资料笔者也是主要从三个链接中理解和概括 阅读详情

我们都知道,iOS的tableView能做到滑动很平滑,一部分是依赖于runloop的mode的切换。当系统检测到有scrollerview滑动时,系统就会将当前进程的主线程切换到UITrackingRunLoopMode,直到滑动结束,又会切换到NSDefaultRunLoopMode。这个过程听起来很奇妙,那么他是怎么做到的呢,我们能不能在需要的时候也这么做呢?

答案是肯定的,我们可以模拟这个过程,我的思路是这样的:由于主线程不是一个runloop干净的线程,所以我们另外启动一个子线程,

    //使用GCD启动一个子线程
    dispatch_async(dispatch_get_global_queue(0, 0), ^{

    });

为了保证线程不退出,我们添加一个timer, 让其在下NSDefaultRunLoopMode模式下运行,按正常情况下,下面的代码会在一直打印“timer1 fired”,该子线程会永远运行在NSDefaultRunLoopMode模式下。

    dispatch_async(dispatch_get_global_queue(0, 0), ^{

        //timer1运行在default mode
        NSTimer *timer1 = [NSTimer timerWithTimeInterval:1.f repeats:YES block:^(NSTimer * _Nonnull timer) {
            NSLog(@"timer1 fired");
        }];
        [[NSRunLoop currentRunLoop] addTimer:timer1 forMode:NSDefaultRunLoopMode];
        [[NSRunLoop currentRunLoop] run];
    });

但是主线程是可以切换mode的,那么这样肯定不行,我们只有改变runloop的启动方式,只有用更好控制的runMode: beforeDate:这个函数,大家知道这个函数运行起来的runloop,会在指定的mode下运行一次便会退出,但是由于我们添加的是timer,所有不会主动退出,但是我们可以采用CFRunLoopStop()主动退出,只有runloop能退出,我们才又机会切换mode,下面是实现代码


    dispatch_async(dispatch_get_global_queue(0, 0), ^{

        //timer1运行在default mode
        NSTimer *timer1 = [NSTimer timerWithTimeInterval:1.f repeats:YES block:^(NSTimer * _Nonnull timer) {
            NSLog(@"timer1 fired");
        }];
        [[NSRunLoop currentRunLoop] addTimer:timer1 forMode:NSDefaultRunLoopMode];

        self.currentMode = kCFRunLoopDefaultMode;
        while (1) {
            [[NSRunLoop currentRunLoop] runMode:self.currentMode beforeDate:[NSDate distantFuture]];
        }
    });

这样写就可以通过控制currentMode这个全局变量来控制runloop下次运行的mode。我们模拟在touchbegan的时候切换到UITrackingRunLoopMode,touchend的时候又切换回NSDefaultRunLoopMode,为了显示runloop确实切换到了UITrackingRunLoopMode,我们启动另一个timer让其运行在UITrackingRunLoopMode,看打印日志就可以了。代码实现是这样的:


    dispatch_async(dispatch_get_global_queue(0, 0), ^{

       self.rl = CFRunLoopGetCurrent();

        //timer1运行在default mode
        NSTimer *timer1 = [NSTimer timerWithTimeInterval:1.f repeats:YES block:^(NSTimer * _Nonnull timer) {
            NSLog(@"timer1 fired");
        }];
        [[NSRunLoop currentRunLoop] addTimer:timer1 forMode:NSDefaultRunLoopMode];

        //timer2运行在track Mode
        NSTimer *timer2 = [NSTimer timerWithTimeInterval:1.f repeats:YES block:^(NSTimer * _Nonnull timer) {
            NSLog(@"timer2 fired");
        }];
        [[NSRunLoop currentRunLoop] addTimer:timer2 forMode:UITrackingRunLoopMode];

        //指定当前运行mode
        self.currentMode = NSDefaultRunLoopMode;
        while (1) {
            [[NSRunLoop currentRunLoop] runMode:self.currentMode beforeDate:[NSDate distantFuture]];
        }
    });


  - (void) touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event {
        NSLog(@"touch began")
        //touchbegan 切换成track mode
        self.currentMode = UITrackingRunLoopMode;
        CFRunLoopStop(self.rl);
   }

   - (void) touchesEnded:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event {
      NSLog(@"touch end");
      //touchend 切换成kCFRunLoopDefaultMode
      self.currentMode = kCFRunLoopDefaultMode;
      CFRunLoopStop(self.rl);
  }

代码运行起来后,就可以看到,在触摸之前只有timer1打印,在手指触摸时之后timer2打印

2020-06-05 14:48:39.932264+0800 [18468:8621222] timer1 fired
2020-06-05 14:48:40.932321+0800 [18468:8621222] timer1 fired
2020-06-05 14:48:41.934566+0800 [18468:8621222] timer1 fired
2020-06-05 14:48:42.934567+0800 [18468:8621222] timer1 fired
2020-06-05 14:48:43.344774+0800 [18468:8620979] touch began
2020-06-05 14:48:43.345429+0800 [18468:8621222] timer2 fired
2020-06-05 14:48:43.934576+0800 [18468:8621222] timer2 fired
2020-06-05 14:48:44.929843+0800 [18468:8621222] timer2 fired
2020-06-05 14:48:45.294261+0800 [18468:8620979] touch end
2020-06-05 14:48:45.294846+0800 [18468:8621222] timer1 fired

通过这样我们就模拟了系统的mode切换过程,也顺便知道了,为什么NSTimer需要设置在NSRunLoopCommonModes模式下运行。

iOS RunLoop的总结 RunLoop是iOS开发核心的事件循环机制,它负责管理线程的生命周期、处理各类事件。主线程的RunLoop默认开启,子线程需要手动获取并维护RunLoop。以上就是对RunLoop的一些总结。 阅读详情

相关推荐

使用Wireshark抓取用户在网站的登陆密码

(POST请求是浏览器向服务器提交数据的方式,我们的用户名和密码就是这样提交出去的),单击点开,发现我们的账号和密码,就被抓取到了,在。(注意哦,要去掉http和/,比如http://www.4399.com/,我们只需要记下4399.com即可)(这句话是筛选数据,就是只显示IP为我们要抓取网站的数据) ,点击右边的蓝色箭头。这就是Wireshark简单的抓取登录密码的教程,只适用于http协议的网站。”打开,是这个样子,上面的数据先不用管,我们先点击左上角红色的方块停止抓包。,然后回车,得到的IP为。

泡泡的博客 1万+

iOS开发 - Runloop的mode是如何切换的

文章目录问题探索Runloop的mode是如何切换的mode切换时会退出吗? 问题 Runloop的mode是如何切换的? Runloop的mode切换时,上一个mode是需要退出吗? 探索 Runloop的mode是如何切换的 UITableView滑动时,Runloop会进行切换mode,由kCFRunLoopDefaultMode切换为UITrackingRunLoopMode,根据源码,切换mode实际是调用CFRunLoopRunSpecific 这个函数 SInt32 CFRunLoopRu

CaicaiNo.1 1855

PostgreSQL高可用之主备复制

多个PostgreSQL可协同工作,如果主库发生宕机备库将迅速进行接管并对外提供服务以实现高可用。本文将从主备复制、主备切换、故障转移等角度进行实际测试演练。第一章主备复制是基础,通过主备复制可以得到一个或多个相同的实例。在主备复制的基础上通过第二章主备切换介绍了如何手工将主库与备库互换角色。在第三章中,采用了Keepalived进行实时监测,在主库宕机后,使用主备切换中提到的命令使备库升级为主库并对外提供服务,以达到PostgreSQL高可用的目标。

asdasdsaff的博客 1348

Runloop应用详解

RunLoop 是 iOS 应用于线程中的一种循环机制。系统本身没有创建 RunLoop 的 API,不过可以通过 currentRunLoop 获取当前 RunLoop。主线程本身就存在一个 RunLoop,而且是运行转态,子线程的 RunLoop 需要手动开启,否知无法监听到输入源与定时源。子线程 RunLoop 随着所在子线程的事件源结束而关闭,随着所在子线程的结束而释放。

风·之痕的博客 1511

【点云数据集】整理汇总(自用,更新ing)

涵盖了各种不同的城市场景:教堂、街道、铁路轨道、广场、村庄、足球场、城堡等等。邮件地址:dmich-request@graphics.stanford.edu,内容需包含:1. 您的姓名、头衔或职位,以及所在机构或隶属关系;license比较难获取,目前可获取的人员:(1)目前隶属于大学、工业研究实验室或其他主要机构的已发表过研究成果的研究人员;普林斯顿 ModelNet 项目的目标是为计算机视觉、计算机图形学、机器人技术和认知科学领域的研究人员提供全面、干净的物体 3D CAD 模型集合。

weixin_44392103的博客 797

深入解析Linux Suspend/Resume机制——从用户态到内核态的完整流程

本文深入解析Linux Suspend/Resume机制,从用户态触发到内核态执行的完整流程。详细介绍了三种挂起模式(Freeze、Standby、Suspend to RAM)的实现原理,包括系统调用入口、状态验证、设备挂起流程及平台相关操作。同时提供实战调试技巧,帮助开发者解决电源管理中的常见问题。

weixin_29313239的博客 444

iOS RunLoop 初识

今天突然才之间才意识到NSTimer这样的运行方式,是在多线程中实现的循环还是在主线程中去实现的呢。当然不可能是在主线程中的while那么简单,那样什么都干不了,简单看了下NSTimer是以同步方式运行的。时间到了,消息发出后,ontimer的函数是在主线程上调用的。 我们会经常看到这样的代码: - (IBAction)start:(id)sender   {   pageStil...

weixin_34143774的博客 156

多传感器标定:如何统一摄像头、雷达与IMU坐标?

多传感器标定:如何统一摄像头、雷达与IMU坐标?​ ,人工智能,计算机视觉,大模型,AI,本文详细阐述多传感器标定中统一摄像头、雷达与 IMU 坐标的方法。先介绍传感器坐标系统、坐标统一必要性及变换数学基础,再分述摄像头与雷达、IMU 与摄像头、IMU 与雷达的标定原理、步骤、参数计算及结果验证,还讲解了多传感器坐标统一的整体流程,分析了标定常见问题及解决办法,介绍了常用标定工具,结合实际案例说明应用,探讨了标定精度的影响因素、提升方法及发展趋势,为相关领域提供了全面的多传感器标定指导。​

不踩坑,不知道坑有多深;不总结,踩过的坑白踩。 12万+

iOS——RunLoop

一、RunLoop简介 Run 表示运行,Loop 表示循环。结合在一起就是运行循环的意思。直观理解就像是不停的跑圈。 RunLoop 实际上是一个对象,这个对象在循环中用来处理程序运行过程中出现的各种事件(比如说触摸事件、UI刷新事件、定时器事件、Selector事件),从而保持程序的持续运行。 RunLoop 在没有事件处理的时候,会使线程进入睡眠模式,从而节省 CPU 资源,提高程序性...

cym_bj 607

2025年微信小程序获取手机号授权登录注册详细教程(含服务端)。不弹窗原因以及减少组件用量的方法

前端把获取到的code传给后端,后端获取access_token和前端传过来的code,请求服务器接口,即可获取到手机号。

coderYYY的博客 3万+

Microsoft Forms功能深度解析:企业数据收集与协作的智能利器

Microsoft Forms是微软365生态中的在线表单工具,支持问卷调查、测验和投票创建,具备拖拽式界面、多题型设计和实时数据分析功能。其核心价值在于易用性、跨平台兼容性以及与Teams、SharePoint等微软服务的深度集成,满足GDPR/HIPAA等合规要求。提供表单创建、权限管理、自动化流程(通过Power Automate)和审计日志等功能,适用于金融、医疗、教育等多行业场景。虽然存在逻辑分支有限等约束,但通过案例证明能显著提升数据收集效率(达70-85%)。使用时需注意许可证配置(Busin

xueyunshengling的博客 9125

NSDefaultRunLoopMode

//成功获得相片还是视频后的回调 - (void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary *)info{     NSURL *videoURL = [info objectForKey:UIImagePickerControlle

lvchaman的专栏 732

SAP B1中文培訓教材_SDK

公司内部培训资料,对开发工具 ,DIAPI, UIAPI,Add-ON有详细解说

iOS Runloop探究及应用

Runloop剖析Runloop初识Runloop是什么Runloop有什么用Runloop怎么用Runloop与线程CFRunloopNSRunloopRunloop相关类Runloop内部执行过程Runloop应用总结 Runloop初识 Runloop是什么 程序运行过程中循环的处理事情,是个do{…}while()循环。 Runloop有什么用 保持程序的持续执行。 处理App中的各种事件(触摸、定时器、performSelector()、线程切换处理等) 节省CPU资源、提高程序性能: 该做事的

zhuxincheng_1218的专栏 1032

Outlook Express 6 (OE6) for Win7/Win8/Win10

英文版 Outlook Express6.0, 兼容Win7/Win10/WinXP,解压就可用。

假人有限元模型

假人模型,车辆碰撞假人有限元模型,适合做乘员安全的研究者利用

RunLoop深度探究以及有关面试题

首先什么是runloop? 顾名思义,运行循环,在程序运行中做一些事情。下面就是一个runloop,让程序不会马上退出,保持运行状态 int main(int argc, char * argv[]) { NSString * appDelegateClassName; @autoreleasepool { // Setup code that might c...

hengsf123456的博客 294

android 蓝牙通讯demo

android 下蓝牙通讯demo,实现了发现蓝牙,使能蓝牙,通过蓝牙发送消息。

RunLoop 深度解析

本文深入解析了iOS/macOS开发中的RunLoop机制。RunLoop是事件处理循环,负责管理线程任务调度,包含Mode、Source、Timer和Observer四大组件。文章详细阐述了RunLoop的基础概念、与线程的关系、基本结构及生命周期,并深入分析了底层运行机制。主要内容包括:RunLoop通过do-while循环检测事件;Mode切换实现不同场景的事件隔离;Source0/Source1的事件处理差异;Timer的实现原理与精度问题;Observer的状态监控机制。RunLoop的合理使用能

CallAuxiliary Blog 1090

iOS——runLoop

RunLoop实际上就是一个对象,这个对象管理了其需要处理的事件和消息,并提供了一个入口函数来执行相应的处理逻辑。线程执行了这个函数后,就会处于这个函数内部的循环中,直到循环结束,函数返回。RunLoop是一种高级的循环机制,让程序持续运行,并处理程序中的各种事件,让线程在需要做事的时候忙起来,不需要的话就让线程休眠。RunLoop和线程是绑定在一起的,每条线程都有唯一一个与之对应的RunLoop对象。不能自己创建RunLoop对象,但是可以获取系统提供的RunLoop对象。

m0_73348697的博客 2737

iOS Runloop探索(快速了解Runloop)

Runloop是一个事件处理循环,用于调度工作并协调接收传入事件。Runloop 的目的是在有工作要做的时候让线程保持忙碌,在没有工作的时候让线程休眠。本篇文章就对Runloop进行一个简单的阐述,希望能帮到需要了解的同仁。

郭永明的技术专栏 4073

Runloop解析

​ RunLoop——运行循环(死循环),它提供了一个事件循环机制在程序运行过程中处理各种事件,例如用户交互、网络请求、定时器等等。RunLoop可以在需要的时候自己跑起来运行,在没有操作的时候就停下来休息,充分节省CPU资源,提高程序性能。

yueliangmua的博客 1435

【iOS】RunLoop学习

这篇博客起源于一个问题,为什么自动轮播图在滑动tableView时就停止滚动了。以上就是我学习RunLoop的总结,后续我讲继续补充完善我的博客。

2401_87841908的博客 400

RunLoop卡顿监控

卡顿主要表现为主线程卡死,不响应用户动作或者响应很慢,这种体验很差,会让用户对产品的认可度急速下滑,如果不及时优化,最终会导致用户流失。 那么,哪些情况会导致主线程卡顿呢?大体有如下几个方面: 很复杂的 UI 、图文混排的绘制量很大; 主线程进行网络同步请求; 主线程上做大量的 IO 操作; 运算量过大,CPU 持续高占用; 死锁和主子线程抢锁。 检测方案 为了优化卡顿,我们需要准确的知道哪里发生了卡顿,然后才能有针对性的进行优化,所以在开始优化之前我们需要去监控卡顿发生的地方。那么问题来了,怎么监控卡

Jerod's blog 404

RunLoop源码剖析---图解RunLoop

文章目录RunLoop源码剖析---图解RunLoop前言什么是RunLoop?RunLoop的作用RunLoop在何处开启?RunLoop对象RunLoop对象的获取CFRunLoopRef对象源码剖析RunLoop和线程RunLoop的相关类RunLoop的相关类之间关系各个类的作用RunLoop中的ModeCFRunLoopModeRef__CFRunLoopMode源码剖析__CFRunL...

qq_42376419的博客 1533

RunLoop

1.RunLoop基本作用: 保持程序持续运行,程序一启动就会开一个主线程,主线程一开起来就会跑一个主线程对应的RunLoop,RunLoop保证主线程不会被销毁,也就保证了程序的持续运行 处理App中的各种事件(比如:触摸事件,定时器事件,Selector事件等) 节省CPU资源,提高程序性能,程序运行起来时,当什么操作都没有做的时候,RunLoop就告诉CUP,现在没有事情做,我要去休息,这时...

Freedom的博客 223

iOS runloop的深入浅出,runloop的理解看这里就够了

一:什么是runloop事件循环,绝对不止是死循环这么简单的一个回答。实质上就是runloop内部状态的转换。1.用户态:应用程序都是在用户态,平时开发用到的api等都是用户态的操作2.内核态:系统调用,牵涉到操作系统,底层内核相关的指令。实际上是计算机内部进行的资源调度操作。1.等待:其实就是用户态-内核态的转换。事件循环不是while死循环,而是状态转换,切记。二:runloop的数据结构NS...

horisea的博客 8069

iOS中关于RunLoop的一些认知

iOS中关于RunLoop的一些认知和面试题,仅供参考,有任何问题欢迎指出!

qq_43658148的博客 617
上一篇: app耗电检测分析以及优化
敬业的程序猿
博客等级 码龄11年 51粉丝 77原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值