ReactiveSwift源码解析(二) Bag容器的代码实现

 今天博客我接着上篇博客的内容来,上篇博客咱们详细的看了ReactiveSwift中的Observer已经Event的代码实现。接下来咱们来看一下ReactiveSwift中的结构体Bag的实现。Bag:袋子,顾明思议,就是用来装东西的,咱们暂且将Bag称之为容器。在ReactiveSwift中的Bag主要是用来存储Signal对象的,咱们在后期介绍ReactiveSwift源码时会陆陆续续的看到Bag的身影。html

由于Bag这个结构体在ReactiveSwift中比较独立,因此咱们本篇博客就来聊一下Bag的具体实现。本篇博客咱们会详细的介绍Bag的代码实现,并从Bag代码实现中看一下Swift语言自己的东西,并给出Bag的测试用例。固然,本篇博客咱们还会涉及到“迭代器模式”,关于“迭代器模式”更详细的信息,请移步于以前发布的关于设计模式的博客《设计模式(十):从电影院中认识"迭代器模式"(Iterator Pattern)》。git

 

1、ContiguousArraygithub

在博客的第一部分咱们先来看一下ContiguousArray的相关内容。由于结构体Bag就是在ContiguousArray的基础上进行封装的,也就是说袋子中的元素最终是存放在ContiguousArray中的。在Swift中ContiguousArray与Array的用法差很少,下方是官方对ContiguousArray的介绍。设计模式

从下方咱们能够清楚的知道ContiguousArray、Array还有ArraySlice的大部分属性和方法是共用的。可是在存储Class或者@objc 协议时,使用ContiguousArray效率会更高一些。可是ContiguousArray不能和Objective-C的NSArray进行桥接,而且不能将ContiguousArray传入到Objective-C的API中。
数组

固然从ContiguousArray名字来看,它是占用连续存储空间的数组。具体请看下方的官方介绍。app

  

 

 

2、Bag的基本实现post

下方是结构体Bag的基本实现,稍后还会介绍Bag的延展以及与其关联的BagElement类型。接下来咱们来详细的看一下其实现。固然下方截图中的代码实现,是将ReactiveSwift中的英文注释给删了,添加了一些中文注释。这样看着更舒服一些。测试

一、RemovalTokenurl

首先咱们来看一下RemovalToken,以及看一下RemovalToken这个类在Bag结构体中所扮演的角色。从下方代码片断中咱们不难看出,RemovalToken是一个空类,中该类的名字咱们能够看出,该类的对象是充当Token用的。也就是说该类的对象能够做为Bag中所存储元素的惟一标示符,而且能够用来删除元素使用。spa

咱们知道,每一个类的对象都会有一个惟一的HashValue。其实在Bag中真正使用到的是RemovalToken的对象所对应的HashValue,这个稍后咱们会聊到。

 

2.Bag的基本实现

从下方代码段中,咱们能够看出Bag是以结构体的形式存在的,并且后边紧跟了一个Element的泛型类型。紧接着是类型为 ContiguousArray<BagElement<Element>> 的泛型数组,BagElement<Element>这个类型稍后会提到。

insert()方法负责插入元素,从代码实现来看其实就是向elements数组后方append元素,添加的元素类型为BagElement。inser()方法由@discardableResult进行修饰,说明insert()方法所返回的值能够被忽略,也就是说若是没有变量来接收insert()的返回值的话,程序并不会报出警告。而insert()前方的 mutating关键字通常用来修饰Swift中的枚举或者结构体中的方法,被mutating关键字修饰的方法就能够修改枚举或者结构体中的属性了。用法以下所示。

接下来咱们来看一下remove()方法,该方法的参数是一个token,其功能就是经过token来删除元素。固然具体代码实现也是比较简单的,就是对elements数组进行遍历,找到元素的token与传入的token一致的话,咱们就将其删除。具体实现以下所示。

  

 

 

3、BagElement结构体的实现

 接下来,咱们来看一下Bag中所存储元素的类型BagElement的实现,代码以下所示。固然实现比较简单,BagElement也是一个泛型结构体,其泛型类型Value其实就是Bag的泛型类型Element。其中有两个属性,一个Value,用来存储值。另外一个是token,用来存储该值对应的惟一标示。

紧接着是BagElement的的延展,用来输出描述信息的,以下所示。

   

 

4、Bag的延展

接下来咱们来看一下Bag的延展,代码以下所示。Bag的延展中的相关内容仍是比较简单的。首先定义了一个Array<Element>.Index的类型别名Index,其实就是Int类型。而后是startIndex和endIndex两个计算属性,用来获取Bag的第一个元素的索引,和结束位置的索引。

subscript()方法是为Bag结构体添加自定义下标,使其支持下标访问元素的形式。makeIterator()方法则用来建立Bag<Element>所对应的迭代器。关于Bag的迭代器,稍后会进行介绍。

  

 

5、Bag的迭代器

接下来我咱们就来看一下Bag容器的迭代器,其实就是“迭代器模式”的具体应用。下方代码段就是Bag的迭代器的具体实现。从下方代码咱们不难看出,BagIterator实现了Swift中的迭代器协议IteratorProtocol,而后给出了迭代器的next()方法的实现。下方咱们将会对该迭代器进行测试。

  

 

6、Bag的测试用例

下方代码片断中是对Bag的测试用例。首先咱们初始化了一个Bag实例,而后指定其泛型类型为String。紧接着咱们又建立了一个bagsTokens的数组,用来存储myBags中每一个元素所对应的token,便于在移除元素时使用。最后是往myBags中添加值了。每添加一个值咱们就记录一下该值所对应的token。

在添加完元素后,咱们能够遍历输出一下每一个token对象的HashValue。而后咱们能够经过token来移除myBags中的元素。

最后咱们能够从myBags中获取相应的迭代器,而后使用迭代器访问myBags中的元素。

  

 

下方是对Bag中的Token以及Bag中的全部元素进行的输出,以下所示:

  

今天博客就先到这儿,下篇博客会继续更新ReactiveSwift相关的东西。

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

相关文章
相关标签/搜索