一、首先 我们先来认识一下 RunLoop

RunLoop: 就是运行循环(在程序运行过程中循环做一些事情)

应用范围:比如 定时器 GCD 事件响应 手势识别 界面刷新 网络请求等等。

先来看一个例子:

ios runloop卡顿检测 ios run loop_App

得到的结果是:程序执行完 14行  程序将会退出。

如果是下面这种写法 ,又会是怎么个情况啦。

ios runloop卡顿检测 ios run loop_用户态_02

 此时 程序并不会马上退出,而是保持运行状态。

UIApplicationMain这个函数并不能看到源码 ,但是它能让程序保持当前状态 ,这其中就用到了RunLoop。

RunLoop基本作用:

         1.保持程序的持续运行

         2.处理APP中的各种事件(比如触摸、定时器等)

         3.节约CPU资源、提高程序性能:该做事时做事,该休息时休息

         4.......

二、在IOS中 有2套API来访问和使用RunLoop

  • Foundation:NSRunLoop 
  • Core Foundation:CFRunLoopRef

三、RunLoop与线程的关系

     1、每条线程都有唯一的一个与之对应的RunLoop对象

     2、RunLoop保存在一个全局的Dictionary里,线程作为key,RunLoop作为value

     3、线程刚创建时并没有RunLoop对象,RunLoop会在第一次获取它时创建

     4、RunLoop会在线程结束时销毁

     5、主线程的RunLoop已经自动获取,子线程默认没有开启RunLoop

 四、RunLoop相关的类

ios runloop卡顿检测 ios run loop_ios runloop卡顿检测_03

其中 CFRunLoopModeRef又是如下结构

ios runloop卡顿检测 ios run loop_主线程_04

CFRunLoopModeRef代表RunLoop的运行模式

一个RunLoop包含了若干个Mode,每个Mode又包含若干个Source0/Source1/Timer/Observer

RunLoop启动时只能选择其中一个Mode,做为当前Mode

如果需要切换Mode,只能退出当前Loop,再重新选择一个Mode进入,不同组的Source0/Source1/Timer/Observer能分割开来,互不影响

如果Mode里面没有任何Source0/Source1/Timer/Observer,RunLoop会立马退出

如图:

ios runloop卡顿检测 ios run loop_用户态_05

 

 我们最常使用的有2种Mode

  • kCFRunLoopDefaultMode(NSDefaultRunLoopMode):App的默认Mode,通常主线程是在这个Mode下运行
  • UITrackingRunLoopMode:界面跟踪 Mode,用于 ScrollView 追踪触摸滑动,保证界面滑动时不受其他 Mode 影响

五、RunLoop的状态

/* Run Loop Observer Activities */

typedef CF_OPTIONS(CFOptionFlags, CFRunLoopActivity) {

    kCFRunLoopEntry = (1UL << 0),                  // 即将进入Loop

    kCFRunLoopBeforeTimers = (1UL << 1),       // 即将处理Timer

    kCFRunLoopBeforeSources = (1UL << 2),    // 即将处理Sources

    kCFRunLoopBeforeWaiting = (1UL << 5),     // 即将进入休眠

    kCFRunLoopAfterWaiting = (1UL << 6),       // 刚从休眠中唤醒

    kCFRunLoopExit = (1UL << 7),                   // 即将退出Loop

    kCFRunLoopAllActivities = 0x0FFFFFFFU

};

 五、RunLoop运行逻辑

ios runloop卡顿检测 ios run loop_ios runloop卡顿检测_06

 

  五、RunLoop休眠的实现原理

RunLoop如果即将进入休眠状态   会从用户态(mach_msg())切换到 内核态(mach_msg())  ----没有消息就让线程休息

有消息就会唤醒线程 重新进入用户态处理消息

 

 

注:如有错误,欢迎大家指正!知识点仅供学习使用!