RunLoop

2020-12-26  本文已影响0人  云溪_Cloud

一、获取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退出的时候也会被释放。

上一篇下一篇

猜你喜欢

热点阅读