RunLoop

turboksiOS70

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图片圆角设置

iOS图片圆角设置

    UIImageView * vv = [[UIImageView alloc] initWithFrame:CGRectMake(50, 500, 250, 25...

多线程举例

多线程举例

举例一:- (void)viewDidLoad {    [super viewDidLoad];    dispatch_queue_t queue = di...

OC对象的本质

OC对象的本质

我们平时编写的oc代码、底层实现其实是C\C++代码OC代码    ——>    C\C++    ——>  &nbs...

Runtime详解

Runtime详解

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

百度地图自定义marker

百度地图自定义marker

#import "HomeViewController.h"#import "PaopaoView.h"@interface HomeViewControlle...

isKindOfClass和isMemberOfClass的区别

isKindOfClass和isMemberOfClass的区别

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