RunLoop是什么?
顾名思义,在程序运行中循环做事情
应用的场景
- 定时器(Timer),PerfomeSelector
- GCD Async Main Queue
- 事件响应,手势识别,界面刷新
- 网络请求
- AutoreleasePool
如果没有RunLoop,程序直接退出:

如果有了RunLoop:
int main(int argc, char * argv[]) {
@autoreleasepool {
return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class]));
}
}

访问和使用RunLoop
- Foundation: NSRunLoop
[NSRunLoop currentRunLoop]; // 获得当前线程的RunLoop对象
[NSRunLoop mainRunLoop]; // 获得主线程的RunLoop对象
- Core Foundation: CFRunLoop
CFRunLoopGetCurrent(); // 获得当前线程的RunLoop对象
CFRunLoopGetMain(); // 获得主线程的RunLoop对象
Core Foundation中关于RunLoop的5个类
- CFRunLoopRef
- CFRunLoopModeRef
- CFRunLoopSourceRef
- CFRunLoopTimerRef
- CFRunLoopObserverRef
typedef struct __CFRunLoop * CFRunLoopRef
struct __CFRunLoop{
pthread_t _pthread;
CFMutableSetRef _commodes;
CFMutableSetRef _commonModeItems;
CFRunLoopModeRef _currentMode;
CFMutableSetRef _modes;
}
typedef struct __CFRunLoopMode * CFRunLoopModeRef
struct __CFRunLoopMode{
CFStringRef _name;
CFMutableSetRef _soruce0;
CFMutableSetRef _source1;
CFMutableArrayRef _observe;
CFMutableArrayRef _timers;
}
CFRunLoopMode和RunLoop的运行模式:
- CFRunLoopModeRef代表RunLoop的运行模式
- 一个RunLoop包含若干个Mode,每个Mode又包含若干个Source0/Source1/Timer/Observer
- RunLoop启动时只能选择其中一个Mode,作为currentMode
- 如果需要切换Mode,只能退出当前Loop,再重新选择一个Mode进入
- 不同组的Source0/Source1/Timer/Observer能分隔开来,互不影响
- 如果Mode里没有任何Source0/Source1/Timer/Observer,RunLoop会立马退出
Source0 : 触摸事件处理 performSelector:onThread:
Source1 : 基于Port的线程间通信 系统事件捕捉
Timers : NSTimer performSelector:withObject:afterDelay:
Observers : 用于监听RunLoop的状态 UI刷新(BeforeWaiting) Autorelease pool(BeforeWaiting)
CFRunLoopObserverRef
typedef CF_OPTIOns(CFOptionFlags,CFRunLoopActivity){
KCFRunLoopEntry = (1UL << 0), //即将进入Loop
KCFRunLoopBeforeTimes = (1UL << 1), //即将处理Timer
KCFRunLoopBeforeSources = (1UL << 2),//即将处理Source
KCFRunLoopBeforeWating = (1UL << 5), //即将进入休眠
KCFRunLoopAfterWating = (1UL << 6), //刚从休眠中唤醒
KCFRunLoopExit = (1UL << 7), //即将进退出Loop
KCFRunLoopAllActivities = 0x0FFFFFFU
}
RunLoop的运行逻辑

常见的2种Mode:
1.kCFRunLoopDefaultMode(NSDefaultRunLoopMode):App的默认Mode,通常主线程是在这个Mode下运行
2.UITrackingRunLoopMode:界面跟踪 Mode,用于 ScrollView 追踪触摸滑动,保证界面滑动时不受其他 Mode 影响
RunLoop与线程的关系
- 每条线程都有唯一一个与之对应的RunLoop对象
- RunLoop保存在一个全局的字典里,key = tread,value = RunLoop
- 线程刚创建时并没有Runloop对象,RunLoop会在第一次获取时创建
- RunLoop会在线程销毁时销毁
- 主线程默认自动开启RunLoop,子线程默认没有开启