文章系列
《RACSignal 》
《RACDisposable》
《RACSubject造虎、RACReplaySubject》
《iOS RAC - 基本用法》
《iOS RAC - 定時器》
《iOS RAC - RACMulticastConnection》
《iOS RAC - RACCommand》
《iOS RAC - 核心方法bind》
《iOS RAC - 集合RACTuple惦费、RACSequence》
《iOS RAC - rac_leftSelector》
《iOS RAC - 映射》
《iOS RAC - 過濾》
《iOS RAC - 登錄頁面司志,MVVM》
之前有提到過RACSignal是不具備發(fā)送信號的能力的,但是RACSubject
這個類就可以做到訂閱/發(fā)送為一體松嘶。
之前還提到過RAC三部曲艘狭,在RACSuject中同樣適用。
<br / >
然后我們先創(chuàng)建一個簡單的代碼段翠订,然后接著分析分析巢音。
//1創(chuàng)建信號,
RACSubject * subject = [RACSubject subject];
//2訂閱信號
[subject subscribeNext:^(id _Nullable x) {
NSLog(@"%@",x);
}];
//3發(fā)送數(shù)據(jù)
[subject sendNext:@"發(fā)送數(shù)據(jù)"];
<br />
-
1. 先看看創(chuàng)建信號會干啥吧
從上圖中可以很直觀的看到 調(diào)用subject
方法內(nèi)部事創(chuàng)建了一個_disposable
取消信號和一個數(shù)組_subscribers
尽超,這個數(shù)組從命名上就可以看出來這個數(shù)組事官撼,用來保存訂閱者。
<br />
-
2. 然后是訂閱信號
- (RACDisposable *)subscribeNext:(void (^)(id x))nextBlock {
NSCParameterAssert(nextBlock != NULL);
RACSubscriber *o = [RACSubscriber subscriberWithNext:nextBlock error:NULL completed:NULL];
return [self subscribe:o];
}
這里很簡單似谁,創(chuàng)建一個訂閱者歧寺,然后調(diào)用 self subscribe:o]
方法燥狰,細心的你可能還記得在RACSignal
中也調(diào)用了這個方法,但是需要注意的是這兩個方法并不是一個方法斜筐,內(nèi)部實現(xiàn)不一樣龙致。
選中這個方法進去
內(nèi)部實現(xiàn)代碼:
通過上面的代碼截圖我們得知了,在訂閱的時候會把訂閱者會把訂閱者保存到一開創(chuàng)建RACSubject
中的數(shù)組_subscribers
中去顷链。
<br />
-
3. 最后是發(fā)布信息
[subject sendNext:@"發(fā)送數(shù)據(jù)"];
點進去繼續(xù)看看內(nèi)部實現(xiàn)吧
<br />
-
總結(jié):
1目代、創(chuàng)建的subject的是內(nèi)部會創(chuàng)建一個數(shù)組
_subscribers
用來保存所有的訂閱者
2、訂閱信息的時候會創(chuàng)建訂閱者嗤练,并且保存到數(shù)組中
3榛了、遍歷subject中_subscribers
中的訂閱者,依次發(fā)送信息
-
所以對于RACSignal不同的地方是:他可以被訂閱多次煞抬,并且只能是先訂閱后發(fā)布霜大。
驗證驗證:
<br />
從上面的代碼中可以明確的看到叠穆,第一次發(fā)送的字符串是沒有收到的梗搅,所以證明了RACSubject只能訂閱之后,發(fā)送數(shù)據(jù)才收到
然后我們訂閱多次信號福稳,然后發(fā)送數(shù)據(jù)残拐,我們可以看到收到了兩次數(shù)據(jù)途茫。
??所以可以得到上面的總結(jié)是沒有錯誤的。
<br />
最后還有一個小問題溪食,那就是如果我非要先發(fā)送在訂閱囊卜,并且也要能收到怎么處理呢?
當然是有辦法的啦错沃,主角來了栅组,自帶(賭神)聲音。枢析。笑窜。。
RACReplaySubject
登疗,他繼承RACSubject
排截,他的目的就是為例解決上面必須先訂閱后發(fā)送的問題。
一樣的三行代碼辐益,運行出來的結(jié)果遇上面的不一致断傲,難道不想看看嘛?哈哈智政,我反正是有興趣了认罩,ok,來分析吧续捂。
<br />
-
1 創(chuàng)建信號
還記得RACSubject就是在init中做了初始化垦垂,不記得就到文章開頭開開宦搬,所以我們直接看他對init做了啥處理吧
<br />
-
2 發(fā)送信號
- (void)sendNext:(id)value {
@synchronized (self) {
[self.valuesReceived addObject:value ?: RACTupleNil.tupleNil];
[super sendNext:value];
if (self.capacity != RACReplaySubjectUnlimitedCapacity && self.valuesReceived.count > self.capacity) {
[self.valuesReceived removeObjectsInRange:NSMakeRange(0, self.valuesReceived.count - self.capacity)];
}
}
}
可以看到代碼中在發(fā)送之前做了一件事情,把要發(fā)送的數(shù)據(jù)保存到數(shù)組中劫拗,然后調(diào)用父類的發(fā)送方法间校,發(fā)送玩了看發(fā)送成功了沒,成功了就刪除數(shù)據(jù)页慷,避免一個數(shù)據(jù)多次發(fā)送憔足。
-
3 訂閱信號
總結(jié):
1、創(chuàng)建的時候會在父類的基礎之上多做一步酒繁,創(chuàng)建一個數(shù)組用來保存發(fā)送的數(shù)據(jù)
2滓彰、發(fā)送數(shù)據(jù),但是此時發(fā)送會失敗啊州袒,為什么揭绑?因為沒有人訂閱啊,我發(fā)給誰啊郎哭。
3他匪、訂閱信號,先遍歷一次保存數(shù)據(jù)的數(shù)組彰居,如果有就執(zhí)行 2 诚纸。