Runloop 小记01

289 阅读2分钟
Runloop 即运行循环

启动一个app,默认在主线程创建一个Runloop,保持程序持续运行,不会程序马上退出,处理app中的各种事件(触摸事件,定时器事件等),节省CPU资源,提高程序性能(在没有事件时休眠,需要处理事件时激活)

应用范畴: 定时器,performselector,GCD,事件响应,界面刷新,网络请求,AutoreleasePool

NSRunLoop *mainRunLoop = [NSRunLoop mainRunLoop]; // 获取主线程的Runloop对象
NSRunLoop *currentRunLoop = [NSRunLoop currentRunLoop]; // 获取当前Runloop对象
  • Runloop与线程

    • 每条线程都有一个与之对应的Runloop对象
    • Runloop保持在一个全局的Dictionary里,线程为key,Runloop为value
    • 线程刚创建时并没有Runloop对象,Runloop在第一次获取它时创建
    • Runloop在线程结束时销毁
    • 主线程的Runloop自动创建,子线程默认没有开启Runloop(除非在子线程里创建一个Runloop)
  • Runloop的五个类

CFRunLoopRef
CFRunLoopModeRef
CFRunLoopSourceRef
CFRunLoopTimerRef
CFRunLoopObserverRef

每个CFRunLoopRef包含多个CFRunLoopModeRef,每个CFRunLoopModeRef包含多个CFRunLoopSourceRef,CFRunLoopTimerRef,CFRunLoopObserverRef

*CFRunLoopRef

struct __CFRunLoop {
    CFMutableSetRef _commonModes;     // 
    CFMutableSetRef _commonModeItems; // 
    CFRunLoopModeRef _currentMode;    // 当前Mode模式
    CFMutableSetRef _modes;           // 包含多个CFRunLoopModeRef的集合
    ...
};
struct __CFRunLoopMode {
    CFStringRef _name;            // Mode Name, 例如 @"kCFRunLoopDefaultMode"
    CFMutableSetRef _sources0;    // 点击,触摸等处理
    CFMutableSetRef _sources1;    // 不同线程间port通信;点击触摸等事件的捕捉,在包装成source0进行处理
    CFMutableArrayRef _observers; // 监听器,UI刷新(通过监听界面在进入runloop休眠前刷新),autorelease
    CFMutableArrayRef _timers;    // 定时器
    ...
};
  1. CFRunLoopModeRef代表RunLoop的运行模式
  2. 一个Runloop包含多个Mode,每个Mode包含多个source0,source1,observer,timer
  3. Runloop启动时只能选择其中一个Mode作为当前Mode
  4. 如果需要切换Mode,只能退出当前loop,在重新选择Mode进入
  5. 如果一个runloop里面没有任何sourec,observer,timer,立即退出
  • CFRunLoopModeRef 主要的两种Mode模式

NSDefaultRunLoopMode App默认的Mode,通常主线程是在这个Mode下运行

UITrackingRunLoopMode 界面跟踪Mode,比如ScrollView触摸滑动,保证界面滑动不受其他Mode影响

  • Runloop的几种状态
typedef CF_OPTIONS(CFOptionFlags, CFRunLoopActivity) {
    kCFRunLoopEntry         = (1UL << 0), // 即将进入Loop
    kCFRunLoopBeforeTimers  = (1UL << 1), // 即将处理 Timer
    kCFRunLoopBeforeSources = (1UL << 2), // 即将处理 Source
    kCFRunLoopBeforeWaiting = (1UL << 5), // 即将进入休眠
    kCFRunLoopAfterWaiting  = (1UL << 6), // 刚从休眠中唤醒
    kCFRunLoopExit          = (1UL << 7), // 即将退出Loop
    kCFRunLoopAllActivities // 所有状态
};