您的位置:首頁>正文

ReactiveSwift源碼解析(十)Lifetime代碼實現

為了之後博客的進行, 本篇博客我們就來聊一下ReactiveSwift框架中的Lifetime類的具體實現。 從Lifetime這個名字中我們就這道, 就是生命週期。 在ReactiveSwift中使用Lifetime來標記一個物件的生命週期, 其實主要功能還是將物件的deinit析構函數通過發送信號量將其回檔出來。 接下來我們就來看一下Lifetime類的實現。 Lifetime類與Event和Observer相似, 也是比較原子性的類, 以原子元件的形式存在於ReactiveSwift中。

下方我們會先給出一個Lifetime的使用示例, 然後根據示例的輸出結果來看一下Lifetime的具體代碼實現, 以及工作原理。

一、Lifetime使用實例

針對Lifetime的特性, 我們給出了下方的示例。 當然ReactiveSwift官網上是沒有關於Lifetime的單獨示例的,

因為Lifetime不單獨的對外服務。 下方就是我們對Lifetime類而寫的示例。

1、lifetime方法實現

首先我們來看一下下方的lifetime方法。 。 首先通過Lifetime類中的make工廠方法創建了一個Lifetime的物件和該物件對應的token。 並且lifetime方法在調用時, 需要一個傳址參數tokenRef, 也就是說tokenRef是inout類型的參數, 通過tokenRef參數可以把make所返回的token傳到函數外部。

然後使用lifetime物件的observeEnded方法來添加兩個觀察者。 後邊緊跟著的尾隨閉包是token被釋放時所執行的閉包塊。 因為lifetime物件除了在lifetime方法中使用到, 再也沒有其他地方的引用了, 根據ARC中Strong類型的特點, 所以在lifetime方法調用結束後lifetime物件就會被釋放掉。 所以我們在lifetime函數的結尾處給出了“lifetime將要被釋放”的Log。

而lifetime方法中的token物件通過tokenRef這個inout類型的參數被方法之外的作用域使用到,

所以在lifetime方法調用結束後token所對應的堆空間並不會被釋放。

2、lifetime方法的調用

在tapLifetimeButton方法中, 我們對上述的lifetime方法進行了調用。 首先我們聲明了一個類型為Any?的tokenRef變數, 該變數在調用lifetime函數時作為參數傳給lifetime方法。 也就是說tokenRef變數引用了lifetime方法中的token物件所對應的堆空間。

當lifetime被調用後, 因為lifetime中的lifetime物件所對應的堆空間只用在lifetime的作用域中被引用到, 所以當該方法執行完畢後, lifetime所對應的堆空間會立即被釋放掉。

當tokenRef被置為nil後, token所對應的堆空間也會被立即釋放掉。 在token被釋放執行token對應的析構函數時, 會給那些通過lifetime的observeEnd方法添加的觀察者發送被析構的消息。 所以token被釋放時, 會執行observeEnd方法的尾隨閉包。

3、運行結果

下方截圖就是上述示例的運行結果, 我們可以根據下方的輸出結果與上述的代碼實現進行對比。 從輸出結果中我們容易知道, lifetime物件是在lifetime方法調用執行後所釋放的。 而在lifetime方法中所分配的token物件所對應的堆空間是在tokenRef被置為nil時所釋放的, 在釋放之前像觀察lifetime的生命週期的觀察者來發送消息。

從運行結果來看, Lifetime這個生命週期的類, 本質上是通過token來標示一個物件的生命週期的, 和Lifetime物件的釋放是沒有什麼直接關係。 稍後, 我們聊Token類以及Lifetime類時, 會一目了然。

二、Lifetime中的內部類Token

看完Lifetime的使用示例, 我們來看一下Lifetime的內部代碼實現。 在Lifetime類的內部定義個了一個Token類。

Token類的物件會在Lifetime中使用到, 稍後會給出Token的使用方式。 接下來我們就先來看看這個Lifetime類內部的Token類的代碼實現。

Token類的實現比較簡單, 一句話概括Token的功能:其中使用了Signal的pipe方法創建了一個ended信號量, 並獲取到了ended信號量發送事件的endedObserver, 然後在deinit析構函數中使用endedObserver的sendCompleted的方法發送Complete事件。 上這句話就概括了Token中的全部功能。

下方就是Token類的代碼實現, 其中有一點需要我們注意的是在Token的ended信號量所發送的Value值的類型是一個無參閉包。 在之後的內容中, 用到的時候在介紹。

三、Lifetime的ended屬性和構造器

聊完Token的代碼實現,我們就來聊一下Lifetime中的物件屬性以及構造器。在Lifetime類中只有一個物件屬性,那就是ended信號量。該信號量的類型也是一個可以發送無參無返回值的閉包的Value。Lifetime的構造器主要就是給ended賦值。具體代碼如下所示。

四、Lifetime的便利構造器、工廠方法以及empty靜態屬性

1、Lifetime的便利構造器

接下來我們就來看一下Lifetime的便利構造器。下方代碼片段中被convenience關鍵字修飾的就是Lifetime的便利構造器。該便利構造器的參數是一個Token類型的物件,而在便利構造器中調用了Lifetime的構造器,將Token物件的ended信號量傳給了Lifetime的構造器。所以Lifetime中的ended信號量其實就是Token物件中的ended信號量。

2、Lifetime的工廠方法

聊完Lifetime的便利構造器後,我們就來聊一下Lifetime的工廠方法。我們在之前的博客中《設計模式(四):從“兵工廠”中探索簡單工廠、工廠方法和抽象工廠模式》詳細的介紹了工廠模式。而下方代碼片段中的make靜態方法在Lifetime類中所扮演的角色就是工廠方法,負責創建Lifetime類的物件。在make方法中主要做了兩件事情,一個是產生實體了一個Token物件token,然後將token傳給Lifetime的便利構造器。最後將token以及Lifetime的便利構造器所創建的Lifetime類的物件以元組的形式進行返回。具體代碼如下所示。

3、Lifetime的empty靜態計算屬性

Lifetime的empty靜態計算屬性類似於Signal的empty靜態計算屬性,從其實現代碼我們可以看出empty所創建的Lifetime物件中的ended信號量是一個Signal.empty類型的信號量。也就是說empty所創建的Lifetime物件是一個已經結束的生命週期。具體代碼如下。

五、observeEnded方法實現

接下來我們來看一下observeEnded方法的代碼實現。該方法的主要目的就是往ended信號量中的Bag容器中添加觀察者的。當觀察者收到的事件是isTerminating時,會執行observeEnded方法所提供的尾隨閉包。

而這個endend信號量本質上就是token物件中的endend信號量。當token物件被析構時,會在token的析構函數中調用endend信號量發送信號的endendObserver的sendComplete方法來發送complete事件,也就是上述代碼在Token類的deinit方法中所作的事情。

六、Lifetime執行原理圖

下方是Lifetime、Token、Signal、Observer間的執行關係圖。在Lifetime類中,token起著至關重要的作用。Lifetime的工作原理中其實是使用Token的物件的生命週期來表示一個物件的生命週期的。如果Lifetime的物件空間被釋放了,但是Token物件所對應的堆空間任然存在,那麼Lifetime所對應的Object的生命週期任然再延續,這一點從上面的代碼示例中可以明確看出。

還是那句話,本質上是使用Token物件的生命週期來表示一個物件的Lifetime。

今天的博客就先到這兒,下篇博客我們會繼續解析ReactiveSwift框架中的其他內容。

三、Lifetime的ended屬性和構造器

聊完Token的代碼實現,我們就來聊一下Lifetime中的物件屬性以及構造器。在Lifetime類中只有一個物件屬性,那就是ended信號量。該信號量的類型也是一個可以發送無參無返回值的閉包的Value。Lifetime的構造器主要就是給ended賦值。具體代碼如下所示。

四、Lifetime的便利構造器、工廠方法以及empty靜態屬性

1、Lifetime的便利構造器

接下來我們就來看一下Lifetime的便利構造器。下方代碼片段中被convenience關鍵字修飾的就是Lifetime的便利構造器。該便利構造器的參數是一個Token類型的物件,而在便利構造器中調用了Lifetime的構造器,將Token物件的ended信號量傳給了Lifetime的構造器。所以Lifetime中的ended信號量其實就是Token物件中的ended信號量。

2、Lifetime的工廠方法

聊完Lifetime的便利構造器後,我們就來聊一下Lifetime的工廠方法。我們在之前的博客中《設計模式(四):從“兵工廠”中探索簡單工廠、工廠方法和抽象工廠模式》詳細的介紹了工廠模式。而下方代碼片段中的make靜態方法在Lifetime類中所扮演的角色就是工廠方法,負責創建Lifetime類的物件。在make方法中主要做了兩件事情,一個是產生實體了一個Token物件token,然後將token傳給Lifetime的便利構造器。最後將token以及Lifetime的便利構造器所創建的Lifetime類的物件以元組的形式進行返回。具體代碼如下所示。

3、Lifetime的empty靜態計算屬性

Lifetime的empty靜態計算屬性類似於Signal的empty靜態計算屬性,從其實現代碼我們可以看出empty所創建的Lifetime物件中的ended信號量是一個Signal.empty類型的信號量。也就是說empty所創建的Lifetime物件是一個已經結束的生命週期。具體代碼如下。

五、observeEnded方法實現

接下來我們來看一下observeEnded方法的代碼實現。該方法的主要目的就是往ended信號量中的Bag容器中添加觀察者的。當觀察者收到的事件是isTerminating時,會執行observeEnded方法所提供的尾隨閉包。

而這個endend信號量本質上就是token物件中的endend信號量。當token物件被析構時,會在token的析構函數中調用endend信號量發送信號的endendObserver的sendComplete方法來發送complete事件,也就是上述代碼在Token類的deinit方法中所作的事情。

六、Lifetime執行原理圖

下方是Lifetime、Token、Signal、Observer間的執行關係圖。在Lifetime類中,token起著至關重要的作用。Lifetime的工作原理中其實是使用Token的物件的生命週期來表示一個物件的生命週期的。如果Lifetime的物件空間被釋放了,但是Token物件所對應的堆空間任然存在,那麼Lifetime所對應的Object的生命週期任然再延續,這一點從上面的代碼示例中可以明確看出。

還是那句話,本質上是使用Token物件的生命週期來表示一個物件的Lifetime。

今天的博客就先到這兒,下篇博客我們會繼續解析ReactiveSwift框架中的其他內容。

同類文章
Next Article
喜欢就按个赞吧!!!
点击关闭提示