RunLoop

作者: 云溪_Cloud | 来源:发表于2020-12-26 11:30 被阅读0次

    一、获取RunLoop

    Foundation
    [NSRunLoop currentRunLoop]; // 获得当前线程的RunLoop对象
    [NSRunLoop mainRunLoop]; // 获得主线程的RunLoop对象
    
    Core Foundation
    CFRunLoopGetCurrent(); // 获得当前线程的RunLoop对象
    CFRunLoopGetMain(); // 获得主线程的RunLoop对象
    

    二、RunLoop与线程关系
    1、每条线程都有唯一的一个与之对应的RunLoop对象
    2、RunLoop保存在一个全局的Dictionary里,线程作为keyRunLoop作为value
    3、主线程的RunLoopmain函数中系统创建,子线程的RunLoop需要主动创建
    4、RunLoop在第一次获取时创建,在线程结束时销毁

    三、RunLoop结构体

    struct __CFRunLoop {
        CFRuntimeBase _base;
        pthread_mutex_t _lock;          /* locked for accessing mode list */
        __CFPort _wakeUpPort;           // used for CFRunLoopWakeUp 
        Boolean _unused;
        volatile _per_run_data *_perRunData;              // reset for runs of the run loop
        pthread_t _pthread;
        uint32_t _winthread;
        CFMutableSetRef _commonModes;
        CFMutableSetRef _commonModeItems;
        CFRunLoopModeRef _currentMode;
        CFMutableSetRef _modes;
        struct _block_item *_blocks_head;
        struct _block_item *_blocks_tail;
        CFAbsoluteTime _runTime;
        CFAbsoluteTime _sleepTime;
        CFTypeRef _counterpart;
    };
    

    CFRunLoopModeRef其实是指向__CFRunLoopMode结构体的指针,CFRunLoopModeRef代表RunLoop的运行模式,一个RunLoop包含若干个Mode,每个Mode又包含若干个Source0/Source1/Timer/Observer,而RunLoop启动时只能选择其中一个Mode作为currentMode
    1、Source1: 基于Port的线程间通信,通过内核和其他线程相互发送消息(与内核相关)
    2、Source0: 非基于Port的,用于主动触发,例如触摸事件,PerformSelectors
    3、Timers: 定时器,NSTimer
    4、Observer: 监听器,用于监听RunLoop的状态
    总结
    CFRunLoopModeRef代表RunLoop的运行模式
    一个RunLoop包含若干个Mode,每个Mode又包含若干个Source、Timer、Observer
    每次RunLoop启动时,只能指定其中一个Mode,这个Mode被称作CurrentMode,如果需要切换Mode,只能退出RunLoop,再重新指定一个Mode进入,这样做主要是为了分隔开不同组的Source、Timer、Observer,让其互不影响。如果Mode里没有任何Source0/Source1/Timer/ObserverRunLoop会立马退出。
    一种Mode中可以有多个Source(事件源,输入源,基于端口事件源例键盘触摸等) Observer(观察者,观察当前RunLoop运行状态) 和Timer(定时器事件源)。但是必须至少有一个Source或者Timer,因为如果Mode为空,RunLoop运行到空模式不会进行空转,就会立刻退出。

    四、RunLoop的运行模式
    RunLoop运行模式一共五种,前两种比较常见
    1、kCFRunLoopDefaultMode:App的默认Mode,通常主线程是在这个Mode下运行
    2、UITrackingRunLoopMode:界面跟踪 Mode,用于 ScrollView 追踪触摸滑动,保证界面滑动时不受其他 Mode 影响
    3、UIInitializationRunLoopMode: 在刚启动 App 时第进入的第一个 Mode,启动完成后就不再使用,会切换到kCFRunLoopDefaultMode
    4、GSEventReceiveRunLoopMode: 接受系统事件的内部 Mode,通常用不到
    5、kCFRunLoopCommonModes: 这是一个占位用的Mode,作为标记kCFRunLoopDefaultMode和UITrackingRunLoopMode用,并不是一种真正的Mode

    五、RunLoop释放机制
    RunLoop内部有一个自动释放池,当RunLoop开启时,就会自动创建一个自动释放池,当RunLoop在休息之前会释放掉自动释放池的东西,然后重新创建一个新的空的自动释放池,当RunLoop被唤醒重新开始跑圈时,Timer,Source等新的事件就会放到新的自动释放池中,当RunLoop退出的时候也会被释放。

    相关文章

      网友评论

          本文标题:RunLoop

          本文链接:https://www.haomeiwen.com/subject/tkawnktx.html