专栏首页我只不过是出来写写iOSRAC(ReactiveCocoa)介绍(六)——RACScheduler

RAC(ReactiveCocoa)介绍(六)——RACScheduler

上一篇介绍了一下RAC订阅信号中,方法实现RACCompoundDisposable真正的订阅者类的相关介绍。 这一篇,将在订阅信号的方法中继续探究,当真正的订阅者初始化之后,后续代码涉及到了RACScheduler类的使用。将针对RACScheduler类进行深入的剖析。

RACScheduler类的使用

先从上图的代码中可以发现,RACScheduler的block代码块中,有执行self.didSubscribe( )代码块的代码,即执行创建信号时的代码块,也就意味着此处的schedule代码块是必须执行。 跳转进入查看schedule方法,可以发现有多个基于RACScheduler的子类,都有该实现方法。 在RACScheduler类中,有三种子类:RACImmediateScheduler、RACSubscriptionScheduler和RACQueueScheduler

schedule方法跳转列表

在RACImmediateScheduler子类看到schedule方法中,是立即执行block代码块。

- (RACDisposable *)schedule:(void (^)(void))block {
    NSCParameterAssert(block != NULL);

    block();
    return nil;
}

接着是RACSubscriptionScheduler子类中的schedule方法实现。

- (RACDisposable *)schedule:(void (^)(void))block {
    NSCParameterAssert(block != NULL);

    if (RACScheduler.currentScheduler == nil) return [self.backgroundScheduler schedule:block];

    block();
    return nil;
}

在RACSubscriptionScheduler子类schedule方法中,在执行代码块之前,会先判断当前线程、当前队列是否为nil。若不为nil,则会在后台开启一个串行异步线程队列。而self.backgroundScheduler通过[RACScheduler scheduler]创建并实例化的,最终可以追溯到以下代码中:

+ (RACScheduler *)schedulerWithPriority:(RACSchedulerPriority)priority name:(NSString *)name {
    return [[RACTargetQueueScheduler alloc] initWithName:name targetQueue:dispatch_get_global_queue(priority, 0)];
}

上述代码意味着是由RACTargetQueueScheduler类初始化,而RACTargetQueueScheduler是RACQueueScheduler的子类。 而RACTargetQueueScheduler类实例化方法实现中,使用GCD在目标线程里创建了一个串行队列。

RACTargetQueueScheduler类实例化方法实现

那么,此时来看下RACQueueScheduler类的schedule方法实现:

- (RACDisposable *)schedule:(void (^)(void))block {
    NSCParameterAssert(block != NULL);

    RACDisposable *disposable = [[RACDisposable alloc] init];

    dispatch_async(self.queue, ^{
        if (disposable.disposed) return;
        [self performAsCurrentScheduler:block];
    });

    return disposable;
}

此处使用GCD开启了一个异步线程,在后台执行下一步操作,作为当前的Scheduler去执行。所以说,RACQueueScheduler类实现的schedule方法是在后台创建一个串行队列异步线程来实现最终的代码块执行。

performAsCurrentScheduler方法实现

在该方法中,首先找到当前的Scheduler队列;然后从当前线程字典中找到关于RACSchedulerCurrentSchedulerKey键值并将RACScheduler自己赋值给它。 如果当前Scheduler队列不为空,则会把当前的Scheduler队列存入到当前线程字典的RACSchedulerCurrentSchedulerKey键值中;若为空,则把当前线程字典的RACSchedulerCurrentSchedulerKey键值内容全部删除。一旦删除,意味着当前线程中的队列已不存在。当队列不存在时,会利用Objective-C的动态机制,会自动修复重启当前的队列。 上面有一段代码:

    @autoreleasepool {
        block();
    }

此段代码中的block执行时,也就是创建RACSignal信号的block中,会有临时变量的产生,autoreleasepool意味着延迟释放。其中涉及到runloop知识范围,此处不做深入讨论。

以上内容主要讲解了RACScheduler类以及三种子类的作用与实现过程原理,后续会继续探究RAC内部实现的具体流程。

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • RAC(ReactiveCocoa)介绍(七)——信号销毁

    在RACSignal信号发送命令执行之后,本着谁创建谁销毁的原则,最后一步必须要进行销毁操作。而销毁操作的执行则由RACDisposable类来完成。 RAC...

    我只不过是出来写写代码
  • iOS开发——解析XML数据

    移动端开发中,与后台服务数据请求打交道,现在通常是以JSON格式数据进行处理交互。最近碰到一个项目,后台数据交互返回XML格式数据,很久没有接触此类数据了,稍微...

    我只不过是出来写写代码
  • CocoaPods安装过程小记

    今年过年时刚买了台MBP,准备在新本上进行开发,顺便记录下安装CocoaPods过程。

    我只不过是出来写写代码
  • 程序员需要了解的硬核知识之汇编语言(一)

    之前的系列文章从 CPU 和内存方面简单介绍了一下汇编语言,但是还没有系统的了解一下汇编语言,汇编语言作为第二代计算机语言,会用一些容易理解和记忆的字母,单词来...

    cxuan
  • Spark Netty与Jetty (源码阅读十一)

      spark呢,对Netty API又做了一层封装,那么Netty是什么呢~是个鬼。它基于NIO的服务端客户端框架,具体不再说了,下面开始。

    用户3003813
  • guake终端复制标签页

    平时习惯用的终端是下拉式终端guake,开多个标签各司其职,热键一按,呼之即来,挥之即去。

    zqb_all
  • 碎片化 | 第四阶段-46-值栈valueStack介绍和原理-视频

    如清晰度低,可转PC网页观看高清版本: http://v.qq.com/x/page/q0567vth0ol.html ValueStack 值栈:(接口) ...

    码神联盟
  • OpenGL ES 绘制贝塞尔曲线

    最近要求为图像设计流线型曲线边框,想着可以用 OpenGL 绘制贝塞尔曲线,再加上模板测试来实现,趁机尝试一波。

    字节流动
  • 超酷炫!5 款图像工具瞬间提高代码逼格!

    平时我们使用着漂亮的 IDE,编译器里的代码颜色丰富、支持高亮,但其实对外分享的时候,比如公众号、微博、Twitter 等社交平台,大部分都不支持代码排版,看代...

    GitHubDaily
  • Web前端-Vue.js必备框架(三)

    vue是一款渐进式javascript框架,由evan you开发。vue成为前端开发的必备之一。

    达达前端

扫码关注云+社区

领取腾讯云代金券