當前位置:
首頁 > 知識 > ReactiveSwift源碼解析(十)Lifetime代碼實現

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方法的尾隨閉包。

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

3、運行結果

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

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

ReactiveSwift源碼解析(十)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值的類型是一個無參閉包。在之後的內容中,用到的時候在介紹。

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

三、Lifetime的ended屬性和構造器

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

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

四、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對象是一個已經結束的生命周期。具體代碼如下。

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

五、observeEnded方法實現

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

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

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

六、Lifetime執行原理圖

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

還是那句話,本質上是使用Token對象的生命周期來表示一個對象的Lifetime。

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

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

喜歡這篇文章嗎?立刻分享出去讓更多人知道吧!

本站內容充實豐富,博大精深,小編精選每日熱門資訊,隨時更新,點擊「搶先收到最新資訊」瀏覽吧!


請您繼續閱讀更多來自 達人科技 的精彩文章:

一份關於webpack2和模塊打包的新手指南
Openresty使用Thrift安裝步驟
自己動手實現OpenGL-OpenGL原來如此簡單(三)
教學小例子:簡易的webSevrer
thinkphp實現無限級分類

TAG:達人科技 |

您可能感興趣

網關 Spring-Cloud-Gateway 源碼解析——路由之RouteDefinitionLocator一覽
AtomicInteger 源碼解析
android 訪問webservice(解析一行代碼實現)
Istio技術與實踐02:源碼解析之Istio on Kubernetes 統一服務發現
Bayesian Personalized Ranking 演算法解析及Python實現
技術解析系列PouchContainer Goroutine Leak 檢測實踐
druid-spring-boot-starter源碼解析
使用 Python的urlliib.parse 庫解析 URL
Photoshop詳細解析CameraRaw插件使用
精讀解析 《When Sophie Gets Angry》
比iPhone SE更香 Switch Lite三大特性解析
osg例子解析-osgsimpleshaders
藉助Jackson的JsonTypeInfo註解實現多態類的解析
新一代 Apple Watch Series 4 將提升解析度
小女友GFRIEND迷你六輯《Time for the moon night》曲目大解析!
fileless malware技術解析及檢測
Marvell第二代ARM處理器ThunderX2解析:不遜Intel至強
深度解析政府監聽工具FinFisher:Windows
視覺中國官網vcg.com域名狀態變為clientHold(暫停解析)
長文解析:Gardenscapes的成功和Playrix的轉型分析