美文网首页
RunLoop相关笔记

RunLoop相关笔记

作者: 一个半吊子工程师 | 来源:发表于2020-09-17 09:34 被阅读0次

    什么是 RunLoop?

    RunLoop 实际上是一个对象,这个对象在循环中用来处理程序运行过程中出现的各种事件(比如说触摸事件、UI刷新事件、定时器事件、Selector事件),从而保持程序的持续运行。
    RunLoop 在没有事件处理的时候,会使线程进入睡眠模式,从而节省 CPU资源,提高程序性能。

    RunLoop作用是什么?

    1、保持程序持续运行
    程序一启动就会开一个主线程,主线程一开起来就会跑一个主线程对应的RunLoop,RunLoop保证主线程不会被销毁,也就保证了程序的持续运行。

    2、处理App中的各种事件
    比如:触摸事件,定时器事件,Selector事件等。

    3、节省CPU资源,提高程序性能
    程序运行起来时,当什么操作都没有做的时候,RunLoop就告诉CUP,现在没有事情做,我要去休息,这时CUP就会将其资源释放出来去做其他的事情,当有事情做的时候RunLoop就会立马起来去做事情。

    RunLoop 和线程

    RunLoop 和线程是息息相关的,我们知道线程的作用是用来执行特定的一个或多个任务,在默认情况下,线程执行完之后就会退出,就不能再执行任务了。这时我们就需要采用一种方式来让线程能够不断地处理任务,并不退出。所以,我们就有了 RunLoop。

    一条线程对应一个RunLoop对象,每条线程都有唯一一个与之对应的 RunLoop 对象
    RunLoop 并不保证线程安全。我们只能在当前线程内部操作当前线程的 RunLoop 对象,而不能在当前线程内部去操作其他线程的 RunLoop 对象方法。
    RunLoop对象在第一次获取 RunLoop创建销毁则是在线程结束的时候。
    主线程的 RunLoop 对象系统自动帮助我们创建好了,而子线程RunLoop对象需要我们主动创建和维护。

    RunLoop 相关类

    下面我们来了解一下Core Foundation框架下关于 RunLoop 的 5 个类,只有弄懂这几个类的含义,我们才能深入了解 RunLoop 的运行机制。

    CFRunLoopRef:代表 RunLoop 的对象
    CFRunLoopModeRef:代表 RunLoop 的运行模式
    CFRunLoopSourceRef:就是 RunLoop 模型图中提到的输入源 / 事件源
    CFRunLoopTimerRef:就是 RunLoop 模型图中提到的定时源
    CFRunLoopObserverRef:观察者,能够监听 RunLoop 的状态改变

    一个RunLoop对象(CFRunLoopRef)中包含若干个运行模式(CFRunLoopModeRef)。而每一个运行模式下又包含若干个输入源(CFRunLoopSourceRef)、定时源(CFRunLoopTimerRef)、观察者(CFRunLoopObserverRef)。

    每次 RunLoop 启动时,只能指定其中一个运行模式(CFRunLoopModeRef),这个运行模式(CFRunLoopModeRef)被称作当前运行模式CurrentMode)。
    如果需要切换运行模式(CFRunLoopModeRef),只能退出当前 Loop,再重新指定一个运行模式(CFRunLoopModeRef)进入
    这样做主要是为了分隔开不同组的
    输入源(CFRunLoopSourceRef)
    定时源(CFRunLoopTimerRef)
    观察者(CFRunLoopObserverRef),让其互不影响 。

    RunLoop原理

    运行逻辑图

    在每次运行开启RunLoop的时候,所在线程的RunLoop会自动处理之前未处理的事件,并且通知相关的观察者。

    顺序如下:
    1.通知观察者RunLoop已经启动
    2.通知观察者即将要开始的定时器
    3.通知观察者任何即将启动的非基于端口的源
    4.启动任何准备好的非基于端口的源
    5.如果基于端口的源准备好并处于等待状态,立即启动;并进入步骤9
    6.通知观察者线程进入休眠状态
    7.将线程置于休眠知道任一下面的事件发生:

      ·某一事件到达基于端口的源
      ·定时器启动
      ·RunLoop设置的时间已经超时
      ·RunLoop被显示唤醒
    

    8.通知观察者线程将被唤醒
    9.处理未处理的事件

    ·如果用户定义的定时器启动,处理定时器事件并重启RunLoop。进入步骤2
    · 如果输入源启动,传递相应的消息
    ·如果RunLoop被显示唤醒而且时间还没超时,重启RunLoop。进入步骤2
    

    10.通知观察者RunLoop结束

    RunLoop应用

    RunLoop应用

    RunLoop常见的几种模式?模式有啥作用?

    1. kCFRunLoopDefaultMode:App的默认Mode,通常主线程是在这个Mode下运行
    2. UITrackingRunLoopMode:界面跟踪 Mode,用于 ScrollView 追踪触摸滑动,保证界面滑动时不受其他 Mode 影响
    3. UIInitializationRunLoopMode: 在刚启动 App 时第进入的第一个 Mode,启动完成后就不再使用
    4. GSEventReceiveRunLoopMode: 接受系统事件的内部 Mode,通常用不到
    5. kCFRunLoopCommonModes: 这是一个占位用的Mode,作为标记kCFRunLoopDefaultMode和UITrackingRunLoo

    RunLoop中的source0、source1

    Source有两个种:Source0Source1

    Source1 :基于mach_Port的,来自系统内核或者其他进程或线程的事件,可以主动唤醒休眠中的RunLoop(iOS里进程间通信开发过程中我们一般不主动使用)。mach_port大家就理解成进程间相互发送消息的一种机制就好。
    Source0:非基于Port的 处理事件,什么叫非基于Port的呢?就是说你这个消息不是其他进程或者内核直接发送给你的。

    简单举个例子:一个APP在前台静止着,此时,用户用手指点击了一下APP界面,那么过程就是下面这样的:
    我们触摸屏幕,先摸到硬件(屏幕),屏幕表面的事件会先包装成Event, Event先告诉source1(mach_port),source1唤醒RunLoop, 然后将事件Event分发给source0,然后由source0来处理。

    如果没有事件,也没有timer,则runloop就会睡眠, 如果有,则runloop就会被唤醒,然后跑一圈。

    相关文章

      网友评论

          本文标题:RunLoop相关笔记

          本文链接:https://www.haomeiwen.com/subject/dfppdktx.html