一、获取RunLoop
Foundation
[NSRunLoop currentRunLoop]; // 获得当前线程的RunLoop对象
[NSRunLoop mainRunLoop]; // 获得主线程的RunLoop对象
Core Foundation
CFRunLoopGetCurrent(); // 获得当前线程的RunLoop对象
CFRunLoopGetMain(); // 获得主线程的RunLoop对象
二、RunLoop与线程关系
1、每条线程都有唯一的一个与之对应的RunLoop
对象
2、RunLoop
保存在一个全局的Dictionary
里,线程
作为key
,RunLoop
作为value
3、主线程的RunLoop
在main函数
中系统创建,子线程的RunLoop
需要主动创建
4、RunLoop
在第一次获取时创建,在线程结束时销毁
三、RunLoop结构体
struct __CFRunLoop {
CFRuntimeBase _base;
pthread_mutex_t _lock; /* locked for accessing mode list */
__CFPort _wakeUpPort; // used for CFRunLoopWakeUp
Boolean _unused;
volatile _per_run_data *_perRunData; // reset for runs of the run loop
pthread_t _pthread;
uint32_t _winthread;
CFMutableSetRef _commonModes;
CFMutableSetRef _commonModeItems;
CFRunLoopModeRef _currentMode;
CFMutableSetRef _modes;
struct _block_item *_blocks_head;
struct _block_item *_blocks_tail;
CFAbsoluteTime _runTime;
CFAbsoluteTime _sleepTime;
CFTypeRef _counterpart;
};
CFRunLoopModeRef
其实是指向__CFRunLoopMode
结构体的指针,CFRunLoopModeRef
代表RunLoop
的运行模式,一个RunLoop
包含若干个Mode
,每个Mode
又包含若干个Source0/Source1/Timer/Observer
,而RunLoop
启动时只能选择其中一个Mode
作为currentMode
。
1、Source1
: 基于Port的线程间通信,通过内核和其他线程相互发送消息(与内核相关)
2、Source0
: 非基于Port的,用于主动触发,例如触摸事件,PerformSelectors
3、Timers
: 定时器,NSTimer
4、Observer
: 监听器,用于监听RunLoop的状态
总结
CFRunLoopModeRef
代表RunLoop
的运行模式
一个RunLoop
包含若干个Mode
,每个Mode
又包含若干个Source、Timer、Observer
每次RunLoop
启动时,只能指定其中一个Mode
,这个Mode
被称作CurrentMode
,如果需要切换Mode
,只能退出RunLoop
,再重新指定一个Mode
进入,这样做主要是为了分隔开不同组的Source、Timer、Observer
,让其互不影响。如果Mode
里没有任何Source0/Source1/Timer/Observer
,RunLoop
会立马退出。
一种Mode
中可以有多个Source
(事件源,输入源,基于端口事件源例键盘触摸等) Observer
(观察者,观察当前RunLoop运行状态) 和Timer
(定时器事件源)。但是必须至少有一个Source
或者Timer
,因为如果Mode
为空,RunLoop
运行到空模式不会进行空转,就会立刻退出。
四、RunLoop的运行模式
RunLoop运行模式一共五种,前两种比较常见
1、kCFRunLoopDefaultMode
:App的默认Mode,通常主线程是在这个Mode下运行
2、UITrackingRunLoopMode
:界面跟踪 Mode,用于 ScrollView 追踪触摸滑动,保证界面滑动时不受其他 Mode 影响
3、UIInitializationRunLoopMode
: 在刚启动 App 时第进入的第一个 Mode,启动完成后就不再使用,会切换到kCFRunLoopDefaultMode
4、GSEventReceiveRunLoopMode
: 接受系统事件的内部 Mode,通常用不到
5、kCFRunLoopCommonModes
: 这是一个占位用的Mode,作为标记kCFRunLoopDefaultMode和UITrackingRunLoopMode用,并不是一种真正的Mode
五、RunLoop释放机制
RunLoop
内部有一个自动释放池
,当RunLoop
开启时,就会自动创建一个自动释放池,当RunLoop
在休息之前会释放掉自动释放池的东西,然后重新创建一个新的空的自动释放池,当RunLoop
被唤醒重新开始跑圈时,Timer,Source
等新的事件就会放到新的自动释放池中,当RunLoop
退出的时候也会被释放。