iOS Runloop 消息循环

2018-02-09 19:27:18来源:cnblogs.com作者:东方🐺人点击

分享
  • 介绍

  Runloop是一种事件监听循环,可以理解成一个while死循环,监听到事件就起来,没有就休息。
  Runloop可以在不同模式下进行切换,iOS有五种模式,其中UIInitializationRunLoopModel应用程序启动时会使用,启动完成后将不再使用;GSEventReceiveRunLoopMode这个是接受系统内部的Model,通常做不到。还有UITrackingRunLoopMode、NSDefaultRunLoopMode、NSRunLoopCommonModes三种模式是我们通常用到的,下文中会详细讲解,其中NSRunLoopCommonModes是一个占位符,NSDefaultRunLoopMode和UITrackingRunLoopMode都会绑定这个占位符。

  • Runloop

- 1.1 字面意思

a 运行循环b 跑圈

- 1.2 基本作用(作用重大)

(1) 保持程序的持续运行(ios程序为什么能一直活着不会死)(2) 处理app中的各种事件(比如触摸事件、定时器事件【NSTimer】、selector事件【选择器·performSelector···】)(3) 节省CPU资源,提高程序性能,有事情就做事情,没事情就休息

- 1.3 重要说明

(1)如果没有Runloop,那么程序一启动就会退出,什么事情都做不了。(2)如果有了Runloop,那么相当于在内部有一个死循环,能够保证程序的持续运行(3)main函数中的Runloop(4)在UIApplication函数内部就启动了一个Runloop,函数返回一个int类型的值(5)这个默认启动的Runloop是跟主线程相关联的

- 1.4 Runloop对象

(1)在iOS开发中有两套api来访问Runloop        a.foundation框架【NSRunloop】        b.core foundation框架【CFRunloopRef】(2)NSRunLoop和CFRunLoopRef都代表着RunLoop对象,它们是等价的,可以互相转换(3)NSRunLoop是基于CFRunLoopRef的一层OC包装,所以要了解RunLoop内部结构,需要多研究CFRunLoopRef层面的API(Core Foundation层面)

- 1.5 Runloop参考资料

(1)苹果官方文档:    https://developer.apple.com/library/mac/documentation/Cocoa/Conceptual/Multithreading/RunLoopManagement/RunLoopManagement.html(2)CFRunLoopRef开源代码下载地址:    http://opensource.apple.com/source/CF/CF-1151.16/

- 1.6 Runloop与线程

(1)Runloop和线程的关系:一个Runloop对应着一条唯一的线程        问题:如何让子线程不死        回答:给这条子线程开启一个Runloop(2)Runloop的创建:主线程Runloop已经创建好了,子线程的runloop需要手动创建(3)Runloop的生命周期:在第一次获取时创建,在线程结束时销毁

- 1.7 获得Runloop对象

(1)获得当前Runloop对象        a. NSRunloop            NSRunLoop * runloop1 = [NSRunLoop currentRunLoop];        b.CFRunLoopRef            CFRunLoopRef runloop2 = CFRunLoopGetCurrent();(2)拿到当前应用程序的主Runloop(主线程对应的Runloop)        a.NSRunloop            NSRunLoop * runloop1 = [NSRunLoop mainRunLoop];        b.CFRunLoopRef            CFRunLoopRef runloop2 = CFRunLoopGetMain();(3)注意点:开一个子线程创建runloop,不是通过alloc init方法创建,而是直接通过调用currentRunLoop方法来创建,它本身是一个懒加载的。(4)在子线程中,如果不主动获取Runloop的话,那么子线程内部是不会创建Runloop的。可以下载CFRunloopRef的源码,搜索_CFRunloopGet0,查看代码。(5)Runloop对象是利用字典来进行存储,而且key是对应的线程Value为该线程对应的Runloop。

- 1.8 Runloop相关类

(1)Runloop运行原理图 (2)五个相关的类  a.CFRunloopRef  b.CFRunloopModeRef【Runloop的运行模式】  c.CFRunloopSourceRef【Runloop要处理的事件源】  d.CFRunloopTimerRef【Timer事件】  e.CFRunloopObserverRef【Runloop的观察者(监听者)】(3)Runloop和相关类之间的关系图(4)Runloop要想跑起来,它的内部必须要有一个mode,这个mode里面必须有source/observer/timer,至少要有其中的一个。

- CFRunloopModeRef

(1)CFRunloopModeRef代表着Runloop的运行模式(2)一个Runloop中可以有多个mode,一个mode里面又可以有多个source/observer/timer等等(3)每次runloop启动的时候,只能指定一个mode,这个mode被称为该Runloop的当前mode(4)如果需要切换mode,只能先退出当前Runloop,再重新指定一个mode进入(5)这样做主要是为了分割不同组的定时器等,让他们相互之间不受影响(6)系统默认注册了5个mode  a.kCFRunLoopDefaultMode:App的默认Mode,通常主线程是在这个Mode下运行  b.UITrackingRunLoopMode:界面跟踪 Mode,用于 ScrollView 追踪触摸滑动,保证界面滑动时不受其他 Mode 影响  c.UIInitializationRunLoopMode: 在刚启动 App 时第进入的第一个 Mode,启动完成后就不再使用  d.GSEventReceiveRunLoopMode: