runloop

  • Run Loop 观察者
  • Run loop 入口
  • Run loop 何时处理一个定时器
  • Run loop 何时处理一个输入源
  • Run loop 何时进入睡眠状态
  • Run loop 何时被唤醒,但在唤醒之前要处理的事件
  • Run loop 终止
  • 手动添加观察者
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
// 创建Observer
/*
第1个参数: 指定如何给observer分配存储空间
第2个参数: 需要监听的状态类型/ kCFRunLoopAllActivities监听所有状态
第3个参数: 是否每次都需要监听
第4个参数: 优先级
第5个参数: 监听到状态改变之后的回调
*/
CFRunLoopObserverRef observer = CFRunLoopObserverCreateWithHandler(CFAllocatorGetDefault(), kCFRunLoopAllActivities, YES, 0, ^(CFRunLoopObserverRef observer, CFRunLoopActivity activity) {
switch (activity) {
case kCFRunLoopEntry:
NSLog(@"即将进入runloop");
break;
case kCFRunLoopBeforeTimers:
NSLog(@"即将处理timer");
break;
case kCFRunLoopBeforeSources:
NSLog(@"即将处理source");
break;
case kCFRunLoopBeforeWaiting:
NSLog(@"即将进入睡眠");
break;
case kCFRunLoopAfterWaiting:
NSLog(@"刚从睡眠中唤醒");
break;
case kCFRunLoopExit:
NSLog(@"即将退出");
break;
default:
break;
}
});
// 给主线程的RunLoop添加一个观察者
/*
第1个参数: 需要给哪个RunLoop添加观察者
第2个参数: 需要添加的Observer对象
第3个参数: 在哪种模式下可以可以监听
*/
CFRunLoopAddObserver(CFRunLoopGetMain(), observer, kCFRunLoopDefaultMode);
// 释放对象
CFRelease(observer);
  • 每次运行 run loop,你线程的runloop对会自动处理之前未处理的消息,并通 知相关的观察者。具体的顺序如下:
  • 1.通知观察者 run loop 已经启动
  • 2.通知观察者任何即将要开始的定时器
  • 3.通知观察者任何即将启动的非基于端口的源
  • 4.启动任何准备好的非基于端口的源
  • 5.如果基于端口的源准备好并处于等待状态,立即启动;并进入步骤 9。
  • 6.通知观察者线程进入休眠
  • 8.将线程置于休眠直到任一下面的事件发生:
  • 某一事件到达基于端口的源
  • 定时器启动
  • Run loop 设置的时间已经超时
  • run loop 被显式唤醒
  • 9.处理未处理的事件
  • 如果用户定义的定时器启动,处理定时器事件并重启 run loop。进入步骤 2
  • 如果输入源启动,传递相应的消息
  • 如果 run loop 被显式唤醒而且时间还没超时,重启 run loop。进入步骤 2
  • 启动 run loop 只对程序的辅助线程有意义。一个 run loop 通常必须包含一个输入源或定时器来监听事件。如果一个都没有,run loop 启动后立即退出。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
/// 1. 通知Observers,即将进入RunLoop
/// 此处有Observer会创建AutoreleasePool: _objc_autoreleasePoolPush();
__CFRUNLOOP_IS_CALLING_OUT_TO_AN_OBSERVER_CALLBACK_FUNCTION__(kCFRunLoopEntry);
do {
/// 2. 通知 Observers: 即将触发 Timer 回调。
__CFRUNLOOP_IS_CALLING_OUT_TO_AN_OBSERVER_CALLBACK_FUNCTION__(kCFRunLoopBeforeTimers);
/// 3. 通知 Observers: 即将触发 Source (非基于port的,Source0) 回调。
__CFRUNLOOP_IS_CALLING_OUT_TO_AN_OBSERVER_CALLBACK_FUNCTION__(kCFRunLoopBeforeSources);
__CFRUNLOOP_IS_CALLING_OUT_TO_A_BLOCK__(block);
/// 4. 触发 Source0 (非基于port的) 回调。
__CFRUNLOOP_IS_CALLING_OUT_TO_A_SOURCE0_PERFORM_FUNCTION__(source0);
__CFRUNLOOP_IS_CALLING_OUT_TO_A_BLOCK__(block);
/// 6. 通知Observers,即将进入休眠
/// 此处有Observer释放并新建AutoreleasePool: _objc_autoreleasePoolPop(); _objc_autoreleasePoolPush();
__CFRUNLOOP_IS_CALLING_OUT_TO_AN_OBSERVER_CALLBACK_FUNCTION__(kCFRunLoopBeforeWaiting);
/// 7. sleep to wait msg.
mach_msg() -> mach_msg_trap();
/// 8. 通知Observers,线程被唤醒
__CFRUNLOOP_IS_CALLING_OUT_TO_AN_OBSERVER_CALLBACK_FUNCTION__(kCFRunLoopAfterWaiting);
/// 9. 如果是被Timer唤醒的,回调Timer
__CFRUNLOOP_IS_CALLING_OUT_TO_A_TIMER_CALLBACK_FUNCTION__(timer);
/// 9. 如果是被dispatch唤醒的,执行所有调用 dispatch_async 等方法放入main queue 的 block
__CFRUNLOOP_IS_SERVICING_THE_MAIN_DISPATCH_QUEUE__(dispatched_block);
/// 9. 如果如果Runloop是被 Source1 (基于port的) 的事件唤醒了,处理这个事件
__CFRUNLOOP_IS_CALLING_OUT_TO_A_SOURCE1_PERFORM_FUNCTION__(source1);
} while (...);
/// 10. 通知Observers,即将退出RunLoop
/// 此处有Observer释放AutoreleasePool: _objc_autoreleasePoolPop();
__CFRUNLOOP_IS_CALLING_OUT_TO_AN_OBSERVER_CALLBACK_FUNCTION__(kCFRunLoopExit);