RAC(ReactiveCocoa)介紹(五)——RACPassthroughSubscriber

上一篇整體分析了RAC的信號流程,這樣對RAC的工作原理有了整體的認識。
接下來將逐步深入了解RAC實現的底層。

RACPassthroughSubscriber類

在上一篇文章的流程分析中,真正的訂閱者是RACPassthroughSubscriber類,它將創建信號、訂閱者與銷毀者進行了關聯。
在RACPassthroughSubscriber類的頭文件中,聲明了一個RACSignal類的成員變量。

@property (nonatomic, unsafe_unretained, readonly) RACSignal *signal;

在聲明的屬性中,定義了signal為unsafe_unretained,意味著signal為弱引用,但又與weak屬性不同。weak屬性當為nil時,對象會自動執行釋放功能,導致該對象無法繼續被使用。而unsafe_unretained同樣作為弱引用,當為nil時卻指針不會自動釋放,保留一個野指針。如果使用此指針,程序會拋出 BAD_ACCESS 的異常。

在此處多問一個為什么,此處信號為什么要使用unsafe_unretained而不是weak屬性修飾?
找了網上的幾處分析,都在說下面這句:
這里之所以不是weak,是因為引用RACSignal僅僅只是一個DTrace probes動態跟蹤技術的探針。如果設置成weak,會造成沒必要的性能損失。

個人理解:unsafe_unretained屬性不會自動將signal變為nil,而weak屬性會自動置為nil。當signal置為nil時,當前signal不再是一個信號類型的對象,就無法再繼續執行訂閱信號、發送信號動作。所以要使用unsafe_unretained屬性保留當前signal的類型,即使變成了野指針。

_signal成員變量傳值

首先,此處的成員變量signal聲明為RACSignal類,是RACPassthroughSubscriber類實例化方法執行時傳入的。而該信號又是從RACDynamicSignal傳來的,RACDynamicSignal持有了當前的subscribe;subscribe繼續向上溯源,找到了在RACSignal類中的[self subscribe:o]方法。那么答案已經顯而易見了,unsafe_unretained屬性的聲明,就是為了防止在此過程中的循環引用。


RACSignal弱引用導圖

在RACSignal類的訂閱方法subscribeNext方法中,當執行訂閱信號時,self通過LLDB打印出的卻是RACDynamicSignal類。


self打印信息

首先RACDynamicSignal類是RACSignal類的子類,此處進行了RACSignal類的分類擴展在分類中實現了subscribeNext方法。在創建信號時,信號類為RACDynamicSignal類。


RACSignal分類

在發送信號時,打印subscriber會發現其所屬類為RACPassthroughSubscriber。


打印結果

self.innerSubscriber對象為RACSubscriber類創建的,最終是執行RACSubscriber類下的sendNext方法,執行nextBlock。在執行時,@synchronized (self)用于保證線程安全

RACPassthroughSubscriber發送信號實現

以上就是針對RACPassthroughSubscriber類的實現進行了一個簡單的分析,后續會不斷補充、修改。


該文章首次發表在 簡書:我只不過是出來寫寫代碼 博客,并自動同步至 騰訊云:我只不過是出來寫寫iOS 博客

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容