Runloop简单触碰

2017-10-24  本文已影响7人  Mory

什么是 runloop?runloop 是做什么的?下面逐步的开始分析

1,什么是runloop?
2,runloop 包含哪些类?
3,runloop 的运行原理?
4,简单使用。

1.1 runloop 的介绍

官方版本:

The programmatic interface to objects that manage input sources.
A NSRunLoop

object processes input for sources such as mouse and keyboard events from the window system, NSPort objects, and NSConnection
objects. A NSRunLoop object also processes NSTimer events.

Your application neither creates or explicitly manages NSRunLoop
objects. Each NSThread object—including the application’s main thread—has an NSRunLoop object automatically created for it as needed. If you need to access the current thread’s run loop, you do so with the class method currentRunLoop.

Note that from the perspective of NSRunLoop, NSTimer objects are not "input"—they are a special type, and one of the things that means is that they do not cause the run loop to return when they fire.

民间版

runloop 就是不停循环的环形跑路,在循环的的过程中不停地监听和响应各种事件(手势、定时器、刷新 UI、selector 事件)。再不需要处理事件的时候就会进入休眠状态。

1.2 runloop和线程之间的纠葛(不离不弃?相濡以沫?)

1:runloop 和线程之间的是一一匹配的,一夫一妻制。
2:无法直接获取其他子线程的 runloop,可以使用 currentRunloop获取当前线程的 runloop。
3:同生共死,线程结束,runloop 随之一起死亡。

2.1 runloop 的相关类

1:CFRunLoopRef:RunLoop的对象
2:CFRunLoopModeRef:运行模式
3:CFRunLoopSourceRef:输入源/事件源
4:CFRunLoopTimerRef:定时源
5:CFRunLoopObserverRef:观察者,监听RunLoop的状态变化

2.1.1 runloop相关类的关系

image.png

2.1.2 CFRunLoopRef

他是基于 Core Foundation 框架的 runloop 对象,获取方式
1:CFRunLoopGetCurrent()
2:CFRunLoopGetMain()

2.1.3 CFRunLoopModeRef 模式

1:kCFRunLoopDefaultMode 》》runloop 运行默认模式
2:UITrackingRunLoopMode 》》追踪用户界面交互模式(常用)
3:UIInitializationRunLoopMode 》》初始化,app 启动调用
4:GSEventReceiveRunLoopMode 》》 系统自身调用
5:kCFRunLoopCommonModes 》》标记模式(常用)

1:默认模式
[NSTimer scheduledTimerWithTimeInterval:2.0 target:self selector:@selector() userInfo:nil repeats:YES];

2:UITrackingRunLoopMode模式
NSTimer *timer = [NSTimer timerWithTimeInterval:2.0 target:self selector:@selector() userInfo:nil repeats:YES];
[[NSRunLoop currentRunLoop] addTimer:timer forMode:UITrackingRunLoopMode];

3:标记模式
[[NSRunLoop currentRunLoop] addTimer:timer forMode:NSRunLoopCommonModes];

2.1.4 CFRunLoopSourceRef 事件源

2.1.5 CFRunLoopTimerRef 定时源

它是基于时间的触发器(NSTimer是对它的上层封装),包括了一个事件长度和一个回调指针。当加入到RunLoop的时候,RunLoop会注册对应的时间点,RunLoop会被自己注册的时间节点事件回调并唤醒,执行注册的时间节点的操作。

2.1.6 CFRunLoopObserverRef 观察者

监听 runloop 的状态

typedef CF_OPTIONS(CFOptionFlags, CFRunLoopActivity) {
    kCFRunLoopEntry = (1UL << 0),               // 即将进入Loop:1
    kCFRunLoopBeforeTimers = (1UL << 1),        // 即将处理Timer:2    
    kCFRunLoopBeforeSources = (1UL << 2),       // 即将处理Source:4
    kCFRunLoopBeforeWaiting = (1UL << 5),       // 即将进入休眠:32
    kCFRunLoopAfterWaiting = (1UL << 6),        // 即将从休眠中唤醒:64
    kCFRunLoopExit = (1UL << 7),                // 即将从Loop中退出:128
    kCFRunLoopAllActivities = 0x0FFFFFFFU       // 监听全部状态改变  
};
    // 创建观察者
    CFRunLoopObserverRef observer = CFRunLoopObserverCreateWithHandler(CFAllocatorGetDefault(), kCFRunLoopAllActivities, YES, 0, ^(CFRunLoopObserverRef observer, CFRunLoopActivity activity) {
        NSLog(@"RunLoop发生改变---%zd",activity);
    });
    // 添加观察者到当前RunLoop中
    CFRunLoopAddObserver(CFRunLoopGetCurrent(), observer, kCFRunLoopDefaultMode);
    
    // 释放observer
    CFRelease(observer);

3 运行原理

苹果官方提供 逻辑图

在一次循环过程中, 告诉观察者自己的状态,以便观察者在合适的时机(通常用于休眠时处理对应注册的事件) ,注册timer回调事件,处理消息队列添加的事件,处理手动加入的block块事件,处理GCD派发的事件,处理来自系统内核发送的指令事件,实时的判定是否超时,是否接到外部退出指令事件。

4. 简单使用

延迟加载网络图片,保证交互流畅

 [self.ImageView performSelector:@selector(setImage:) withObject:downLoadImage delay:0 inMode:NSDefaultRunLoopMode];

解决定时器 NSTimer 和用户滑动的响应冲突问题,上面已经说了。可将NSTimer 添加到标记模式 commonMode

常驻后台的线程,首先要创建一个强引用的线程。

  [[NSRunLoop currentRunLoop] addPort:[NSPort port] forMode:NSDefaultRunLoopMode];
  [[NSRunLoop currentRunLoop] run];
上一篇 下一篇

猜你喜欢

热点阅读