ReactiveSwift源码解析(八) SignalProducer的代码的基本实现

时间:2022-08-30 15:14:14

在前面几篇博客中我们详细的聊了ReactiveSwift中的Bag、Event、Observer以及Signal的使用方式和代码实现。那么在接下来的这几篇博客中,我们就依附于之前博客的基础上来聊一聊SignalProducer的用法以及内部的代码实现。从SignalProducer的名字中,我们容易知道,SignalProducer是信号量的生产者,确切的说,SignalProducer基于Signal的又一层封装。扩充了Signal的使用方式,使其更贴近于一些业务场景,比如网络的请求等。

接下来我们看一下SignalProducer的基本实现,也就是看一下SignalProducer一些核心的构造器和核心的方法。并且给出这些构造器以及核心方法的代码解释并给出其对应的使用方式。

一、SignalProducer的核心属性、方法和构造器

开门见山,在本篇博客的第一部分我们先给出SignalProducer结构体的核心属性、构造器和方法。下方会对这些SignalProducer的核心内容进行介绍,然后再看一下其具体的使用和运行方式。之所以说本部分所介绍的内容是SignalProducer的核心,因为SignalProducer的其他方法、构造器是在下方所要介绍的内容的基础上所建立起来的。

1、startHandler属性、init(startHandler)构造器以及startWithSignal()的方法实现

startHandler属性是SignalProducer结构体的基本实现中的唯一属性。从下方代码片段中我们可以看出startHandler的类型是一个闭包类型。该闭包类型的的参数是ObserverDisposable类型的对象,返回值为空。

而紧接着下方的init(startHandler)构造器就是为startHandler属性赋值的。虽然该init(startHandler)构造方法简单,但是是SignalProducer结构体的核心,因为在SignalProducer其他构造器中直接或者间接调用了下方的构造方法,稍后我们会给出相应的代码实现。

  ReactiveSwift源码解析(八) SignalProducer的代码的基本实现

上述代码片段中的startWithSignal(setup)方法,也是SignalProducer结构体中比较核心的方法。因为在SignalProducer结构体的扩展方法中直接或者间接的调用了该方法。该方法中做的事情比较单一,就是调用Signal的pipe()方法创建了一个signal对象与该对象所对应的observer对象。该方法的参数是一个名为setup的闭包,将创建的signal对象交给setup()闭包,将observer对象交给startHandler()闭包。而startHandler的闭包体就是init(startHandler)构造器的尾随闭包。

2、上述属性和方法的使用

上述的属性和方法之所以是SignalProducer结构体的核心,是因为SignalProducer的其他构造器以及扩展方法都是在此基数上构建起来的,稍后我们会介绍到。现在我们来看一下上述方法的调用方式。下方就是我们给出的针对上述方法的示例和输出结果。

  • 首先调用了SignalProducer的init(startHandler)构造器,创建了一个producer常量。在该构造器的尾随闭包中,我们可以通过闭包回调的形式获取到producer中signal对象所对应的observer,我们可以通过该对象发送一些值,如下所示。
  • 然后我们创建了一个Observer类的subscribe1对象,并给出了该观察者的Value事件的处理闭包。
  • 最后我们调用startWithSignal启动producer的信号量,通过startWithSignal()方法的尾随闭包,我们可以获取到producer中的signal对象,然后将我们创建的subscriber观察者与该signal进行关联。关联后,subscriber或收到producer中的observer对象所发送的Value事件。

最下方就是该段代码的运行结果,如下所示。

  ReactiveSwift源码解析(八) SignalProducer的代码的基本实现

二、SignalProducer中的其他构造器

上面我们聊了SignalProducer的核心构造器,在SignalProducer结构体的构造器阵营中,其构造器都是在上述核心构造器的基础上衍生出来的快捷构造器。这些衍生出来的构造器适用于特定场景下的SignalProducer的初始化,其功能更为专一,使用更为便捷。接下来我们就来介绍一下这些衍生构造器的代码实现以及使用方式。

1、init(signal)和init(value)

下方代码片段就是init(signal)和init(value)的具体实现,从下方代码片段中我们容易看出,最终都是调用的上述我们介绍的init(startHandler)这个构造器。只不过在startHandler这个闭包块中所做的事情不同罢了。

  ReactiveSwift源码解析(八) SignalProducer的代码的基本实现

我们先来看init(signal),该构造器接收一个signal信号量,然后将producer中的observer对象添加为该参数signal信号量的观察者,也就是说当这个信号量发送消息是,producer中的observer会收到这个外部信号量发过来的消息,然后通知producer中内部的信号量的所有观察者。针对上述代码实现我们可以画出下方的简图。左边的mySignal就是通过init(signal)构造器传过来的信号量对象,mySignal信号量中的Bag中存储了一些该信号量的观察者。然后调用SignalProducerinit(signal)方法将mySignal信号量传给SignalProducer,然后将SignalProducer中的内部信号量signal所对应的observe添加到mySignalBag中,使其成为mySignal信号量的观察者。具体如下所示,稍后我们会给出具体使用方式。

  ReactiveSwift源码解析(八) SignalProducer的代码的基本实现

上述init(value)构造器就简单的多了,就是在调用init(startHandler)构造器的尾随闭包中调用SignalProducer内部的observer将init(value)提供的参数发送出去。发送完毕后就调用Observer的sendCompleted()方法,完成信号量的发送。

接下来我们来看一下上述两个构造器的使用示例以及示例的运行结果。

  • 首先我们来看一下init(signal)的使用示例。首先创建了一个mySignal信号量以及该信号所对应的myObserver。然后调用init(signal)构造器,并把mySignal对象传给该构造器。接着通过startWithSignal()方法往producer中的signal中添加一个名为subscriber1观察者。然后调用myObserver发送Value信号量,我们能看到,producer中信号量的观察者subscriber1也能收到该信号量。
  • 而init(value)构造器的使用就简单许多,直接在SignalProducer创建时,将SignalProducer所对应的信号量所需要发送的值传进去即可,如下所示。

  ReactiveSwift源码解析(八) SignalProducer的代码的基本实现

2、init(action)、init(error)以及init(result)构造器

接下来我们再来看一下这init(action)、init(error)以及init(result)三个构造器,这个三个构造器也是直接或者间接的调用了我们之前的核心构造器init(startHandler)。下方就是这三个构造器的具体代码实现:

  • init(action)构造器接收了一个名为action的无参闭包,该闭包的返回值为Value。从其代码实现我们不难看出,下方代码就等同于self.init(value: action())。action闭包的作用就是为observer.send(value)提供值的。
  • init(error)构造器中就是在调用init(startHandler)时,在其尾随闭包中的获取到observer然后调用send(error)方法,发送Failure事件。
  • init(result)构造器接收的是一个Result枚举对象,目的就是将Result枚举中的success转换成Value事件,将failure结果转换成failure事件并发送相应的Error。

因为该三个构造方法比较简单,就不提供相应的使用示例了,如果你感兴趣,可以在官方提供的Playground中进行示例的编写。

  ReactiveSwift源码解析(八) SignalProducer的代码的基本实现

3、init(values)和init(first, second, tail…)构造器

本小节我们就来聊一下init(values)和init(first, second, tail)这两个构造器,这两个构造器的功能其实差不多,实现方式也是相同的,只不过是调用方式不同。下方是这两个构造器具体的代码实现。

  • init(values)构造器接收的是一个可遍历的序列,在具体的代码实现中,我们遍历该序列,取出其中的每个值,然后调用observer的send(value)方法将该值进行发送。遍历完成后,调用了sendCompleted()方法完成信号量的发送。
  • init(first, second, tail ...)构造器是一个不定参构造器。在该构造器中,我们将收到的参数组合成数组,然后调用init(values)构造器,具体实现如下。

  ReactiveSwift源码解析(八) SignalProducer的代码的基本实现

针对上述的构造器,我们给出了下方这两个使用示例,以及相应示例的输出结果。

  ReactiveSwift源码解析(八) SignalProducer的代码的基本实现

今天的博客就先到这儿,下篇博客我们会继续解析ReactiveSwift框架中的其他内容。

上述代码github分享地址:https://github.com/lizelu/TipSwiftForRac

ReactiveSwift源码解析(八) SignalProducer的代码的基本实现的更多相关文章

  1. ReactiveSwift源码解析(十一) Atomic的代码实现以及其中的Defer延迟、Posix互斥锁、递归锁

    本篇博客我们来聊一下ReactiveSwift中的原子性操作,在此内容上我们简单的聊一下Posix互斥锁以及递归锁的概念以及使用场景.然后再聊一下Atomic的代码实现.Atomic主要负责多线程下的 ...

  2. ReactiveSwift源码解析(三) Signal代码的基本实现

    上篇博客我们详细的聊了ReactiveSwift源码中的Bag容器,详情请参见<ReactiveSwift源码解析之Bag容器>.本篇博客我们就来聊一下信号量,也就是Signal的的几种状 ...

  3. ReactiveSwift源码解析&lpar;五&rpar; SignalProtocol的observe&lpar;&rpar;、Map、Filter延展实现

    上篇博客我们对Signal的基本实现以及Signal的面向协议扩展进行了介绍, 详细内容请移步于<Signal中的静态属性静态方法以及面向协议扩展>.并且聊了Signal的所有的g功能扩展 ...

  4. Laravel源码解析之model(代码)

    本篇文章给大家带来的内容是关于Laravel源码解析之model(代码),有一定的参考价值,有需要的朋友可以参考一下,希望对你有所帮助. 前言 提前预祝猿人们国庆快乐,吃好.喝好.玩好,我会在电视上看 ...

  5. ReactiveSwift源码解析&lpar;一&rpar; Event与Observer代码实现

    ReactiveCocoa这个框架是做什么用的本篇博客就不做过多赘述了,什么是"响应式编程"也不多聊了,自行Google吧.本篇博客的主题是解析ReactiveCocoa框架中的核 ...

  6. ReactiveSwift源码解析&lpar;二&rpar; Bag容器的代码实现

    今天博客我接着上篇博客的内容来,上篇博客我们详细的看了ReactiveSwift中的Observer已经Event的代码实现.接下来我们来看一下ReactiveSwift中的结构体Bag的实现.Bag ...

  7. ReactiveSwift源码解析&lpar;四&rpar; Signal中的静态属性静态方法以及面向协议扩展

    上篇博客我们聊了Signal的几种状态.Signal与Observer的关联方式以及Signal是如何向关联的Observer发送事件的.本篇博客继续上篇博客的内容,来聊一下Signal类中静态的ne ...

  8. jQuery 源码解析&lpar;八&rpar; 异步队列模块 Callbacks 回调函数详解

    异步队列用于实现异步任务和回调函数的解耦,为ajax模块.队列模块.ready事件提供基础功能,包含三个部分:Query.Callbacks(flags).jQuery.Deferred(funct) ...

  9. ReactiveSwift源码解析&lpar;九&rpar; SignalProducerProtocol延展中的Start、Lift系列方法的代码实现

    上篇博客我们聊完SignalProducer结构体的基本实现后,我们接下来就聊一下SignalProducerProtocol延展中的start和lift系列方法.SignalProducer结构体的 ...

随机推荐

  1. 2019年台积电进军AR芯片,将用于下一代iPhone

    近日,有报道表示台积电10nm 芯片可怜的收益率可能会对 2017 年多款高端移动设备的推出产生较大的影响,其中自然包括下一代 iPhone 和 iPad 机型.不过,台积电正式驳斥了这一说法,表明1 ...

  2. Oracle 11g的Redo Log和Archive Log的分析方法

    自Oracle 11g起,无需设置UTL_FILE_DIR就可以使用LOGMNR对本地数据库的日志进行分析,以下是使用LOGMNR的DICT_FROM_ONLINE_CATALOG分析REDO和归档日 ...

  3. WEB UI 整理

    当下对于网站前段开发人员来说,很少有人不使用一些JS框架或者WEB UI库,因此这些可以有效提高网站前段开发速度,并且能够统一开发环境,对于不同浏览器的兼容性也不需要程序员操心,有了这些优点,当然大家 ...

  4. python 安装第三方模块

    在Python中,安装第三方模块,是通过setuptools这个工具完成的. 如果你正在使用Mac或Linux,安装setuptools本身这个步骤就可以跳过了. 如果你正在使用Windows,请首先 ...

  5. uva 11081 - Strings&lpar;LCS&rpar;

    题目链接:11081 - Strings 题目大意:给出三个字符串,从分别从第一个字符串和第二个字符串中挑选子串a,b,用a和b组成第三个字符串,问可组成的子串有多少种. 解题思路:说起来惭愧啊,题目 ...

  6. Android - 建设项目的版本号

    建设项目的版本号 本文地址: http://blog.csdn.net/caroline_wendy 依据SVN中的项目, 构建本地版本号, 进行开发, 构建方式是: 1. "svn co& ...

  7. 【转】Appium基于安卓的各种FindElement的控件定位方法实践

    原文地址:http://blog.csdn.net/zhubaitian/article/details/39754041#t11 AppiumDriver的各种findElement方法的尝试,尝试 ...

  8. BASE1&lpar;matlab&rpar;

    version memory clc clear tab键 F5键  运行m文件 F9键  只运行选中的 Ctrl+R  注释 Ctrl+T  反注释 Ctrl+I   格式化代码 edit xxx. ...

  9. ANSYS中的阻尼damper

    详情请见链接: ANSYS中的阻尼 ANSYS动力学分析中的阻尼

  10. ATM Mechine &lpar;概率DP&rpar;

    题意:去银行取最多K钱,想要全部取完,但是有个限制就是如果你输入取钱的额度超过了你已有的钱,那么会接受一次警告并无法取钱,然后求最多不超过w次警告的前提下你取完所有钱所需要的最少次数. 思路:概率DP ...