iOS之RunLoop
RunLoop 是 iOS 和 OS X 开发中非常基础的一个概念,对于iOS系统上的APP来说:有了RunLoop的存在进而保证程序的持续运行。网上的资料太多,但是太多都比较晦涩,于是自己整理一些;
写在最前:iOS关于
RunLoop
的学习框架有两套:OC的Foudation
框架和C语言的Core Foundation
框架;
在看了源码以及相关资料整理一下笔记:
Q:线程与RunLoop
之间的关系:
A:一般来讲,每条线程都有唯一的与之对应的RunLoop对象;
Q:RunLoop
在何时被创建?
A:在程序启动时候会默认创建主线程,与主线程对应的RunLoop
在程序启动时候已自动创建并启动;而子线程的RunLoop
则需要手动去创建;
Q:RunLoop
在何时被销毁?
A:主线程的RunLoop
不会被销毁,而子线程的RunLoop
在子线程内的任务结束时被销毁;
Q:RunLoop
如何创建?
A:此时要注意,一般的OC语言创建对象是alloc init来创建,RunLoop
在源码内部为懒加载设计,当获取到当前的RunLoop
为nil,则会自动创建,并且只创建一次。
Q:如何获取RunLoop
对象?
A:获取主线程的RunLoop
对象:[NSRunLoop mainRunLoop];
获取子线程的RunLoop
对象:[NSRunLoop currentRunLoop];
Q:与RunLoop
相关的有哪些类?
A:五个类(结合下面的图):
CFRunLoopRef
CFRunLoopModeRef
— 运行模式
CFRunLoopTimeRef
— 定时器
CFRunLoopSourceRef
— 事件
CFRunLoopObserverRef
— 观察者
下面我们结合这五个类来一一了解:
CFRunLoopModeRef — 运行模式
系统提供了五种模式:
1,kCFRunLoopDefaultMode
:系统默认模式,主线程的RunLoop
模式;
2,UITrackingRunLoopMode
:界面跟踪Mode
,用于跟踪scroview
触摸滑动;
3,UIInitializationRunLoopMode
:在刚启动APP时进入的第一种Mode
,APP启动后该模式即废弃不再使用;
4,GSEventReceiveRunLoopMode
:接收系统事件的内部Mode
;(graphic service
内部绘图渲染等)
5,kCFRunLoopCommonMode
:占位模式,并不是真正的Mode
;
每次RunLoop
启动都要指定一个Mode
,此Mode
为CurrentMode
;RunLoop
可以在多个模式之间切换;如果要切换Mode
,只能退出Loop
,再次重新指定一个Mode
;区别开不同的Source/Timer/Observer
,使其彼此互不干扰;
CFRunLoopTimeRef — 基于时间的触发器;
其实就是NSTimer
,大家对于NSTimer
应该都比较熟悉,再次就不做过多解释;
CFRunLoopSourceRef -- 事件源(输入源)
在官方文档上,分类如下:
Port-Based Sources
Custom Input Sources
Cocoa perform Selector Sources
但是在实践过程中我们按照函数调用栈来分:
Source0
:非基于Port的;
Source1
:基于Port的,通过内核和其他线程通信,用来接收、分发系统事件;
CFRunLoopObserverRef — 观察者模式
能够监听RunLoop
状态的改变;
可以监听的事件(或者说状态)见官方文档截图:
kCFRunLoopEntry = (1UL << 0),
//即将进入Loop
kCFRunLoopBeforeTimers = (1UL << 1),
//即将处理Timer
kCFRunLoopBeforeSources = (1UL << 2),
//即将处理source
kCFRunLoopBeforeWaiting = (1UL << 5),
//即将进入休眠
kCFRunLoopAfterWaiting = (1UL << 6),
//从休眠状态中唤醒
kCFRunLoopExit = (1UL << 7),
//即将退出Loop
kCFRunLoopAllActivities = 0x0FFFFFFFU
//``所有的状态
以上就是RunLoop
的一些概念性的东西,有些枯燥,在接下来我会结合代码和实际场景进行演示,希望能与大家共同学习,共同进步;