实际上就是一个do...while
循环
xxxxxxxxxx
int32_t result;
do {
CHECK_FOR_FORK();
} while ( result);
apple
不允许直接创建runloop
,只提供两个自动获取的函数:CFRunLoopGetMain()
和CFRunLoopGetCurrent()
2,线程和runloop
是一一对应的,保存在一个全局的NSDictionary
里。只能在当前线程中操作当前线程的runloop
,不能操作其他线程的runloop
3,runloop
在第一次获取
的时候创建
,在线程结束的时候销毁
。
4,内部实现如下:
xxxxxxxxxx
/// 全局的Dictionary,key 是 pthread_t, value 是 CFRunLoopRef
static CFMutableDictionaryRef loopsDic;
/// 访问 loopsDic 时的锁
static CFSpinLock_t loopsLock;
/// 获取一个 pthread 对应的 RunLoop。
CFRunLoopRef _CFRunLoopGet(pthread_t thread) {
OSSpinLockLock(&loopsLock);
if (!loopsDic) {
// 第一次进入时,初始化全局Dic,并先为主线程创建一个 RunLoop。
loopsDic = CFDictionaryCreateMutable();
CFRunLoopRef mainLoop = _CFRunLoopCreate();
CFDictionarySetValue(loopsDic, pthread_main_thread_np(), mainLoop);
}
/// 直接从 Dictionary 里获取。
CFRunLoopRef loop = CFDictionaryGetValue(loopsDic, thread));
if (!loop) {
/// 取不到时,创建一个
loop = _CFRunLoopCreate();
CFDictionarySetValue(loopsDic, thread, loop);
/// 注册一个回调,当线程销毁时,顺便也销毁其对应的 RunLoop。
_CFSetTSD(..., thread, loop, __CFFinalizeRunLoop);
}
OSSpinLockUnLock(&loopsLock);
return loop;
}
CFRunLoopRef CFRunLoopGetMain() {
return _CFRunLoopGet(pthread_main_thread_np());
}
CFRunLoopRef CFRunLoopGetCurrent() {
return _CFRunLoopGet(pthread_self());
}
CFRunLoopRef
:RunLoop
对象CFRunLoopModeRef
:运行模式CFRunLoopSourceRef
:输入源/事件源 source1/source0CFRunLoopTimerRef
:定时源CFRunLoopObserverRef
:观察者
Source0
:非基于Port
的。只包含了一个回调(函数指针),它并不能主动触发事件。使用时,你需要先调用CFRunLoopSourceSignal(source)
,将这个Sourc
e 标记为待处理,然后手动调用CFRunLoopWakeUp(runloop)
来唤醒RunLoop
,让其处理这个事件。比如UIView的刷新。Source1
:基于Port
的,通过内核和其他线程通信,接收、分发系统事件。这种Source
能主动唤醒RunLoop
的线程。创建常驻线程就是在线程中添加一个NSport
来实现的。
kCFRunLoopDefaultMode
:默认模式,主线程是在这个运行模式下运行UITrackingRunLoopMode
:跟踪用户交互事件(用于 ScrollView 追踪触摸滑动,保证界面滑动时不受其他Mode影响)UIInitializationRunLoopMode
:在刚启动App时第进入的第一个 Mode,启动完成后就不再使用GSEventReceiveRunLoopMode
:接受系统内部事件,通常用不到kCFRunLoopCommonModes
:伪模式,不是一种真正的运行模式,实际是kCFRunLoopDefaultMode
和 UITrackingRunLoopMode
的结合。NSDictionary
里。只能在当前线程中操作当前线程的runloop
,不能操作其他线程的runloop
。详见内部实现1RunLoop
,只有获取的时候才会创建[[NSRunLoop currentRunLoop] run]
main
线程默认开启Runloop
的NSRunLoop
隶属于:Foundation
,而CFRunLoop
隶属于Core Foundation
CFRunLoop
需要自己手动管理内存,实际上Core Foundation
大部分都是手动管理runloop
实际上是一个do...while
监听事件循环,在不同的model
下接受不同的事件(time/source/observer)
,直到线程结束被销毁。