上一篇整體分析了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聲明為RACSignal類,是RACPassthroughSubscriber類實例化方法執行時傳入的。而該信號又是從RACDynamicSignal傳來的,RACDynamicSignal持有了當前的subscribe;subscribe繼續向上溯源,找到了在RACSignal類中的[self subscribe:o]方法。那么答案已經顯而易見了,unsafe_unretained屬性的聲明,就是為了防止在此過程中的循環引用。
在RACSignal類的訂閱方法subscribeNext方法中,當執行訂閱信號時,self通過LLDB打印出的卻是RACDynamicSignal類。
首先RACDynamicSignal類是RACSignal類的子類,此處進行了RACSignal類的分類擴展在分類中實現了subscribeNext方法。在創建信號時,信號類為RACDynamicSignal類。
在發送信號時,打印subscriber會發現其所屬類為RACPassthroughSubscriber。
self.innerSubscriber對象為RACSubscriber類創建的,最終是執行RACSubscriber類下的sendNext方法,執行nextBlock。在執行時,@synchronized (self)用于保證線程安全
以上就是針對RACPassthroughSubscriber類的實現進行了一個簡單的分析,后續會不斷補充、修改。
該文章首次發表在 簡書:我只不過是出來寫寫代碼 博客,并自動同步至 騰訊云:我只不過是出來寫寫iOS 博客