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  

相關文章
相關標籤/搜索