runloop源码地址:源码下载
runloop官方介绍:查看文档
runloop的源码在corefundation框架中,fundation里边的runloop是基于corefundation里的runloop封装的,corefundation是开源的,所以可以通过runloop的源码进行分析。
什么是runloop
runloop的字面理解就是一个运行循环。从runloop的源码中,可以清晰的看出runloop是一个对象,有入口函数,进入函数可以看到程序里边执行的是do...while循环操作,在do...while循环中处理一些操作。
图一
runloop的作用
runloop和普通的do...while程序对比:
图二
图三
- runloop是一个运行循环,保证程序能够持续的运行,不会退出程序。
- runloop不仅仅是个循环,而是进行了优化能够节省cpu的资源,提高程序的性能。使线程有工作就工作,没有工作就就开始休眠。
- runloop能够处理app中的许多事件如:用户的触摸事件、NSTimer的定时器事件、performSelector的延迟任务事件、通知事件和线程之间的通讯事件等。
runloop和线程的关系
1.runloop的创建、存储及获取
图四
图五
如上两幅图可以看到主线程及线程的runloop的创建及获取过程。
- 当全局的__CFRunloops可变字典不存在时,创建全局__CFRunloops字典。
- 使用主线程来创建主线程的runloop对线。
- 把主线程和主线程的runloop对象使用key和value的方式存储到全局的__CFRunloops字典.
- 获取runloop对象时,使用线程作为key在全局的__CFRunloops字典获取runloop。
-
线程与主线程的runloop创建、存储及获取方式是一样的。
图六
如上图示例代码可知:
- 主线程的runloop默认是开启的,而子线程的runloop默认是不开启的。
- 子线程的的runloop需要在子线程执行:
[[NSRunLoop currentRunLoop] run];
runloop才能运行,子线程才能不退出线程。
2.runloop与线程的关系总结
- 线程与runloop是一一对应的.
- 通过线程才能创建,存储及获取runloop.
- 如果没有线程,runloop是没有意义的。
- 主线程的runloop默认是开启的。
- 子线程的runloop是不开启的。
runloop与modes及items之间的关系
1.runloop对象
图七
由上图runloop的结构体可以看出:
- runloop是一个对象。
- runloop对象里边包含多个mode对象。
- runloop对面里边包含多个item对象。
- runloop对象里边有一个线程对象
2.mode对象
图八
由mode的结构体可以看出:
- mode对象里边包含多个sources0,sources1对象。
- mode对象里边包含多个observer及timer对象。
- 上述包含的这些对象都是item对象。
3.关系图
图九
线程和runloop是一一对应的,runloop和mode是1对多的关系,mode和item也是1对多的关系。runloop只能在一个mode下运行,mode之间可以来回切换。
4.五种mode模式
runloop在五种mode模式下处理事件及消息的机制是不一样的:
- kCFRunLoopDefaultMode:app的默认mode,通常创建runloop时,默认的mode.
- UITrackingRunLoopMode:界面滑动时的mode,确保在界面滑动时,不受别的mode影响。
- UIInitializationRunLoopMode:app刚启动时的mode,启动完成之后不再使用此mode.
- GSEventReceiveRunLoopMode:接收系统内部mode,一般不用。
- kCFRunLoopCommonModes:是一种混合mode类型。
5.三种item
- CFRunLoopSourceRef:分为source0和source1.
- source0:处理app的内部事件如触摸屏幕。
- source1:一般被用于线程之间的通讯。
- CFRunLoopTimerRef:用于NSTimer定时器.
- CFRunLoopObserverRef:用于监听runloop的状态。