1、Mode成员分工

Source0:
触摸事件处理
performSelector:onThread:

Source1:
基于Port的线程间通信
系统事件捕捉

Timers:
NSTimer
performSelector:withObject:afterDelay:

Observers:
用于监听RunLoop的状态
UI刷新(BeforeWaiting)
Autorelease pool(BeforeWaiting)

2、RunLoop状态

  1. typedef CF_OPTIONS(CFOptionFlags, CFRunLoopActivity) {
  2. kCFRunLoopEntry = (1UL << 0),// 进入RunLoop
  3. kCFRunLoopBeforeTimers = (1UL << 1),// 即将处理Timer
  4. kCFRunLoopBeforeSources = (1UL << 2),// 即将处理Source
  5. kCFRunLoopBeforeWaiting = (1UL << 5),// 即将进入休眠
  6. kCFRunLoopAfterWaiting = (1UL << 6),// 即将结束休眠
  7. kCFRunLoopExit = (1UL << 7), // 退出Loop
  8. kCFRunLoopAllActivities = 0x0FFFFFFFU
  9. };

可以通过给当前RunLoop添加observer查看各个状态:

  1. // 给RunLoop添加observer
  2. - (void)addRunLoopObserver {
  3. // 创建Observer
  4. CFRunLoopObserverRef observer = CFRunLoopObserverCreate(kCFAllocatorDefault, kCFRunLoopAllActivities, YES, 0, observeRunLoopActicities, NULL);
  5. // 添加Observer到RunLoop中
  6. CFRunLoopAddObserver(CFRunLoopGetMain(), observer, kCFRunLoopCommonModes);
  7. // 释放
  8. CFRelease(observer);
  9. }
  10. void observeRunLoopActicities(CFRunLoopObserverRef observer, CFRunLoopActivity activity, void *info)
  11. {
  12. switch (activity) {
  13. case kCFRunLoopEntry:
  14. NSLog(@"kCFRunLoopEntry");
  15. break;
  16. case kCFRunLoopBeforeTimers:
  17. NSLog(@"kCFRunLoopBeforeTimers");
  18. break;
  19. case kCFRunLoopBeforeSources:
  20. NSLog(@"kCFRunLoopBeforeSources");
  21. break;
  22. case kCFRunLoopBeforeWaiting:
  23. NSLog(@"kCFRunLoopBeforeWaiting");
  24. break;
  25. case kCFRunLoopAfterWaiting:
  26. NSLog(@"kCFRunLoopAfterWaiting");
  27. break;
  28. case kCFRunLoopExit:
  29. NSLog(@"kCFRunLoopExit");
  30. break;
  31. default:
  32. break;
  33. }
  34. }

*除了使用C语言方法回调,也可以使用block作为回调

3、RunLoop的运行逻辑

image.png

3、RunLoop休眠实现原理

当没有事件需要处理时,RunLoop会进入休眠状态,休眠并不是通过while循环阻塞线程,而是调用mach_msg方法,使用内核层面的功能,让线程进入内核态,等有新的事件需要处理时,再返回用户态。
image.png