1、概念
RunLoop
与线程关联的,是一种事件处理环,用来安排和协调到来的事件,目的就是让其关联的线程在有事件到达时时刻保持运行状态,而当没有事件需要处理时进入睡眠状态从而节约资源,每一个线程都可以有一个RunLoop
对象与之对应,并且是在第一次获取它是系统自动创建的,比如主线程关联的RunLoop
,我们都知道程序的入口函数是main
函数,下面是创建工程后Xcode
自动生成的main.m
文件的main
函数代码:
int main(int argc, char * argv[]) {
@autoreleasepool {
return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class]));
}
}
该方法执行体被autoreleasepool
包围,所以程序可以使用ARC
来管理内存,后面会讲解RunLoop
与autoreleasepool
的关系,main
函数直接返回了UIApplicationMain
函数,该函数内部就会第一次获取RunLoop
对象,所以系统就会创建这样一个RunLoop
对象,因此在没有满足特定条件的时候该主线程不会退出,应用就可以持续运行而不会退出。
在官方文档中使用下图描述RunLoop
模型:
从上图可以看出一个线程会关联一个RunLoop
对象,RunLoop
对象会一直循环,直到超时或收到退出指令。在无限循环的过程中会一直处理到来的事件,右侧将事件分为了两类,一类是Input sources
这部分包括基于端口的source1
事件,开发者提交的各种source0
事件,调用performSelector:onThread:
方法事件,还有一类Timer sources
这个就是常用的定时器事件,这些事件在程序运行期间会不断产生之后会由RunLoop
对象检测并负责处理相关事件。
2、RunLoop
源码解析
RunLoop
有两个对象,NSRunLoop
和CFRunLoopRef
,区别在于由Core Foundation
框架提供的CFRunLoopRef
是纯C语言编写的,提供的也是C语言接口,这些接口都是线程安全的,由Foundation
框架提供的NSRunLoop
是面向对象的,它是基于CFRunLoopRef
的封装,提供的都是面向对象的接口,但这些接口不是线程安全的,Core Foudation
框架是开源的,可以在这个地址下载:Core Foundation开源代码,本文接下来的内容主要是针对该开源代码进行讲解。
首先,看一下在代码中如何获取RunLoop
对象,在Foundation
框架中的NSRunLoop
类提供了如下两个类属性:
//获取当前线程关联的RunLoop对象
@property (class, readonly, strong) NSRunLoop *currentRunLoop;
//获取主线程关联的RunLoop对象
@property (class, readonly, strong) NSRunLoop *mainRunLoop
对应的Core Foundation
里提供下面两个函数来获取RunLoop
对象
//获得当前线程关联的RunLoop对象
CFRunLoopGetCurrent();
// 获得主线程关联的RunLoop对象
CFRunLoopGetMain();
具体细节可以查阅这里:深入理解RunLoop
网友评论