RunLoop

turboksiOS265

2361104-a26b59b5d1cbee74.png

RunLoop

一、基础理论

顾名思义

1.    运行循环

2.    在程序运行过程中循环做一些事情

3.    是用户态和内核态之间的交互模式

应用范畴:

1.    定时器(Timer)、PerformSelector

2.    GCD Async Main Queue

3.    事件响应、手势识别、界面刷新

4.    网络请求

5.    AutoreleasePool

RunLoop的基本作用:

1.    保持程序的持续运行

2.    处理APP中的各种事件(比如触摸事件、定时器事件等)

3.    节省CPU资源、提高程序性能,该做事时做事,该休息时休息

RunLoop中有两套API来访问和使用RunLoop

Foundation:NSRunLoop

Core Foundation:CFRunLoopRef

NSRunLoop和CFRunLoopRef都代表着RunLoop对象,NSRunLoop时基于CFRunLoopRef的一层OC包装。

二、RunLoop与线程的关系

1.    每条线程都有唯一的一个与之对应的RunLoop对象。

2.    RunLoop保存在一个全局的字典里,线程作为key、RunLoop作为value。

3.    线程刚创建时并没有RunLoop对象,RunLoop会在第一次获取它的时候创建。

4.    RunLoop会在线程结束时销毁。

5.    主线程的RunLoop已经自动获取(创建),子线程默认没有开启RunLoop。

三、获取RunLoop对象

Foundation:

[NSRunLoop currentRunLoop]; // 获得当前线程的RunLoop对象

[NSRunLoop mainRunLoop]; // 获得主线程的RunLoop对象

Core Foundation:

CFRunLoopGetCurrent(); // 获得当前线程的RunLoop对象

CFRunLoopGetMain(); // 获得主线程的RunLoop对象

四、RunLoop相关的类

Core Foundation中关于RunLoop的5个类:

一:CFRunLoopRef:

二:CFRunLoopModeRef:

    1.    代表RunLoop的运行模式

    2.    一个RunLoop包含若干个Mode、每个Mode又包含若干个Source0/Source1/Timer/Observer

    3.    RunLoop启动时只能选择其中一个Mode,作为currentMode

    4.    如果需要切换Mode、只能退出当前Loop,再重新选择一个Mode进入

        -    不同组的Source0/Source1/Timer/Observer 能分隔开来,互不影响

    5.    如果Mode里没有任何的Source0/Source1/Timer/Observer,RunLoop会立马退出

常见的两种Mode:

kCFRunLoopDefaultMode(NSDefaultRunLoopMode):APP的默认Mode,通常主线程是在这个Mode模式下运行。

UITrackingRunloopMode:界面跟踪Mode,用于ScrollView追踪触摸滑动,保证界面滑动时不受其他Mode的影响。

三:CFRunLoopSourceRef

四:CFRunLoopTimerRef

五:CFRunLoopObserverRef


2361104-359bbb58065729dc.png

CFRunLoopObserverRef

五、RunLoop的运行逻辑



2361104-549973402a768ed1.png

逻辑

Source0:

    -    触摸事件处理

    -    performeSelector:onThread:

Source1:

    -    基于Port的线程间通信

    -    系统事件捕捉

Timers:

    -    NSTimer

    -    performSelector:withObject:afterDelay:

Observers:

    -    用于监听RunLoop的状态

    -    UI刷新(BeforeWaiting)

    -    Autorelease pool(BeforeWaiting)



2361104-ef8723d81e0dbf5d.png

运行逻辑

01、通知Observers:进入Loop

02、通知Observers:即将处理Timers

03、通知Observers:即将处理Sources

04、处理Blocks

05、处理Source0(可能会再次处理Blocks)

06、如果存在Source1,就跳转到第8步

07、通知Observers:开始休眠(等待消息唤醒)

08、通知Observers:结束休眠(被某个消息唤醒)

01> 处理Timer

02> 处理GCD Async To Main Queue

03> 处理Source1

09、处理Blocks

10、根据前面的执行结果,决定如何操作

01> 回到第02步

02> 退出Loop

11、通知Observers:退出Loop

六、RunLoop在实际开发中的应用

控制线程生命周期

解决NSTimer在滑动时停止工作的问题

监控应用卡顿

性能优化


相关文章

iOS的block

iOS的block

一:block的本质1.    block本质上是一个OC对象,它内部有个isa指针2.    block是封装了函数调用以及函数调用环境的OC对象3.&nbs...

Runtime详解

Runtime详解

The Objective-C language defers as many decisions as it can from compile time and link time to runti...

isKindOfClass和isMemberOfClass的区别

isKindOfClass和isMemberOfClass的区别

+ (BOOL)isMemberOfClass:(Class)cls {//    类的元类 与 传入类 对比    return object_getClas...

dealloc

dealloc

当调用dealloc方法的时候,执行顺序可以在源码中查找如下(objc源码):1.// Replaced by NSZombies- (void)dealloc {    _obj...

暗黑模式适配

暗黑模式适配

先上效果图:正常暗黑一:首先确定自己的主题色比如正常模式下显示紫色、暗黑显示下显示灰色。二:在Assets中新建颜色:创建颜色进行设置:设置颜色左边是正常模式的颜色、右边是暗黑模式下三:举例使用&nb...

iOS的分类(Category)

iOS的分类(Category)

一:Category的底层结构定义在objc-runtime-new.h中:struct category_t {    const char *name;   ...