美文网首页
iOS RunLoop

iOS RunLoop

作者: 开心的小赵 | 来源:发表于2020-09-17 14:41 被阅读0次

写在前面

文章是对网络上的一些讲解做了自己的整理,方便自己理解。

概念

什么是RunLoop?

RunLoop是什么?为什么要有RunLoop?一般来说,一个线程只能执行一个任务,执行完就退出。如果我们需要一种机制,让线程不退出,随时能处理事件,那么我们就用到了RunLoop。

RunLoop又称之为运行循环,内部就是一个do-while循环(可以这么理解,但是实际上是用户状态的改变)。在这个循环内部不断的处理各种事务,保证程序持续运行。RunLoop存在的目的就是当线程中有任务的时候,保证线程干活,当线程没有任务的时候,让线程睡眠,提高程序性能,节省资源,该做事的时候做事,该休息的时候休息。

用户状态改变:
在mian函数,也就是APP启动之后生成了一个runloop,这个runloop并不是死循环,事件处理实际上是用户状态的改变。当有事件的时候,处理事件,内核态转换为用户态。当没有事件处理的时候,用户态转换为内核态。

作用

1、保持程序持续运行
App一启动就会开启主线程,主线程在开启的时候就会开启主线程对应的RunLoop,RunLoop能保证线程不被销毁,主线程不销毁,程序就会持续运行。

2、处理App中各类事件
事件响应、手势识别、界面刷新、AutoreleasePool自动释放池、NSTimer等事件处理。

3、节省CPU资源,提高程序性能
如概述所述,当线程中有任务的时候,保证线程干活,当线程没有任务的时候,让线程睡眠,提高程序性能,节省资源,该做事的时候做事,该休息的时候休息。

深入理解

先有线程 然后才会有runloop【重要】

1.一个runloop 包含若干个mode,当启动一个runloop时会先指定一个mode。检查指定的mode是否存在或者mode是否包含 source和timer,如果不存在就说明是一个空的mode,然后runloop直接退出。

image1.png

2.runloop 官方模型图

image2.png

一个runloop包含 input sources 和 timer sources,通过这个两个来源接受事件到线程中去处理,在没有事件的时候让线程休息。

3.Core Foundation 框架的关于runloop的5个类

CFRunLoopRef:代表runloop对象
  • Core Foundation框架获取runloop
CFRunLoopGetCurrent();// 获取当前线程的runloop
CFRunLoopGetMain();// 获取主线程runloop
  • Foundation框架获取runloop
[NSRunLoop currentRunLoop];
[NSRunLoop mainRunLoop];
CFRunLoopModeRef:代表runloop运行模式

系统默认定义了多种运行模式:(前面三种是开发中用到的模式)

  • kCFRunLoopDefaultMode 【APP的默认模式,主线程中在这个模式下运行】
  • UITrackingRunLoopMode 【跟踪用户交互事件,例如在scrollView滚动的时候,】
  • kCFRunLoopCommonModes 【伪模式,不是一种真正的模式】
  • UIInitializationRunLoopMode 【在刚启动APP时进入第一个mode,启动完成后就不再使用】
  • GSEventReceiveRunLoopMode【接收系统内部事件,通常用不到】
CFRunLoopSourceRef:代表模型中的输入源/事件源
  • Port-Based Sources(基于端口)
  • Custom Input Sources(自定义)
  • Cocoa Perform Selector Sources
CFRunLoopTimerRef:定时源
  • NSTimer
CFRunLoopObserverRef:观察者监听Runloop状态变化

CFRunLoopObserverRef是观察者,用来监听RunLoop的状态改变,CFRunLoopObserverRef可以监听的状态改变有以下几种:

typedef CF_OPTIONS(CFOptionFlags, CFRunLoopActivity) {
    kCFRunLoopEntry = (1UL << 0),               // 即将进入Loop:1
    kCFRunLoopBeforeTimers = (1UL << 1),        // 即将处理Timer:2    
    kCFRunLoopBeforeSources = (1UL << 2),       // 即将处理Source:4
    kCFRunLoopBeforeWaiting = (1UL << 5),       // 即将进入休眠:32
    kCFRunLoopAfterWaiting = (1UL << 6),        // 即将从休眠中唤醒:64
    kCFRunLoopExit = (1UL << 7),                // 即将从Loop中退出:128
    kCFRunLoopAllActivities = 0x0FFFFFFFU       // 监听全部状态改变  
};

4.逻辑图

image3.png

相关文章

网友评论

      本文标题:iOS RunLoop

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