RACSubject、RACReplaySubject(內(nèi)附冷信號(hào)和熱信號(hào)的區(qū)別)

文章系列
《ReactiveCocoa 概述》
《RACSignal》
《RACDisposable》
《RACSubject快集、RACReplaySubject(內(nèi)附冷信號(hào)和熱信號(hào)的區(qū)別)》
《集合RACTuple、RACSequence》
《RAC 中的通知廉白、代理个初、KVO, 基本事件、方法的監(jiān)聽(tīng)》
《rac_liftSelector》
《RACMulticastConnection》
《RACCommand》
《RAC - 核心方法bind》
《RAC - 定時(shí)器》
《RACScheduler》
《RAC - 點(diǎn)擊獲取驗(yàn)證碼 demo》
《RAC - 映射(Map & flattenMap)》
《RAC信號(hào)操作解釋合集》
《RAC - 信號(hào)的生命周期》

  • RACSubject

RACSignal 是冷信號(hào), 不能夠自己發(fā)送信號(hào), 需要訂閱者訂閱, 特點(diǎn)是確定未來(lái), 也就是知道什么時(shí)候結(jié)束/終止, 無(wú)視訂閱者, 不管誰(shuí)訂閱, 都是從頭開(kāi)始執(zhí)行一段老代碼

幫助理解: 冷信號(hào) 相當(dāng)于 劇本, 當(dāng)訂閱者訂閱時(shí), 就相當(dāng)于開(kāi)始拍戲, 不管誰(shuí)訂閱, 都是從頭開(kāi)始拍, 拍完了也就結(jié)束了.

RACSubject 繼承自RACSignal, 是熱信號(hào), 也就是說(shuō)既可以充當(dāng)信號(hào)猴蹂,也可以發(fā)送信號(hào), 并不確定什么時(shí)候終止, 關(guān)心訂閱者, 先來(lái)先得院溺、后來(lái)少得

幫助理解: 熱信號(hào) 相當(dāng)于 拍好的戲, 當(dāng)訂閱者訂閱時(shí), 就開(kāi)始演戲, 接下來(lái)再有訂閱者訂閱, 演到哪里就繼續(xù)演, 不會(huì)重新從頭開(kāi)始, 即先來(lái)的看得多、后來(lái)看的就少.

代碼分析:

    // 1.創(chuàng)建信號(hào)
    RACSubject *subject = [RACSubject subject];
    
    // 2.訂閱信號(hào)
    [subject subscribeNext:^(id  _Nullable x) {
        NSLog(@"x = %@", x);
    }];
    
    // 3.發(fā)送數(shù)據(jù)
    [subject sendNext:@10];

↓[RACSubject subject] 內(nèi)部實(shí)現(xiàn)↓

+ (instancetype)subject {
    return [[self alloc] init];
}

- (instancetype)init {
    self = [super init];
    if (self == nil) return nil;

    // 創(chuàng)建一個(gè) 復(fù)合的_disposable 對(duì)象, 用于取消訂閱
    _disposable = [RACCompoundDisposable compoundDisposable];
    // 創(chuàng)建一個(gè) _subscribers 訂閱者集合, 用來(lái)保存訂閱者
    _subscribers = [[NSMutableArray alloc] initWithCapacity:1];
    
    return self;
}

↓ 訂閱信號(hào) subscribeNext: 內(nèi)部實(shí)現(xiàn)↓
其實(shí)內(nèi)部也RACSignal 信號(hào)訂閱大致相同, 唯一不同的是subscribe: 方法的實(shí)現(xiàn):

- (RACDisposable *)subscribe:(id<RACSubscriber>)subscriber {
    NSCParameterAssert(subscriber != nil);

    RACCompoundDisposable *disposable = [RACCompoundDisposable compoundDisposable];
    subscriber = [[RACPassthroughSubscriber alloc] initWithSubscriber:subscriber signal:self disposable:disposable];

    NSMutableArray *subscribers = self.subscribers;
    @synchronized (subscribers) {
        // 注意: 每次訂閱, 都將訂閱者添加至 信號(hào)內(nèi)部的_subscribers 數(shù)組中
        [subscribers addObject:subscriber];
    }
    
    [disposable addDisposable:[RACDisposable disposableWithBlock:^{
        @synchronized (subscribers) {
            // Since newer subscribers are generally shorter-lived, search
            // starting from the end of the list.
            NSUInteger index = [subscribers indexOfObjectWithOptions:NSEnumerationReverse passingTest:^ BOOL (id<RACSubscriber> obj, NSUInteger index, BOOL *stop) {
                return obj == subscriber;
            }];

            if (index != NSNotFound) [subscribers removeObjectAtIndex:index];
        }
    }]];

    return disposable;
}

↓ 發(fā)布消息sendNext: 內(nèi)部實(shí)現(xiàn)↓

- (void)sendNext:(id)value {
    // 遍歷_subscribers 集合, 向每一個(gè)訂閱者發(fā)送sendNext: 消息, 即所有訂閱者依次發(fā)送消息
    [self enumerateSubscribersUsingBlock:^(id<RACSubscriber> subscriber) {
        [subscriber sendNext:value];
    }];
}
總結(jié)
  1. 創(chuàng)建的subject的是內(nèi)部會(huì)創(chuàng)建一個(gè)數(shù)組_subscribers用來(lái)保存所有的訂閱者
  2. 訂閱信息的時(shí)候會(huì)創(chuàng)建訂閱者磅轻,并且保存到數(shù)組中
  3. 遍歷subject中_subscribers中的訂閱者珍逸,依次發(fā)送信息

注意

RACSubject 可以被訂閱多次,并且只能是先訂閱后發(fā)布, 因?yàn)?先發(fā)送, 再有訂閱者, 訂閱者收不到訂閱之前的消息, 所以稱(chēng)之為先來(lái)先得, 晚來(lái)少得
  • RACReplaySubject
    針對(duì)RACSubject 的注意點(diǎn), 偏偏要先發(fā)送消息, 再去訂閱信號(hào), 該怎么辦呢???

這里就可以使用RACReplaySubject , 它繼承自RACSubject, 目的就是來(lái)解決先發(fā)送信號(hào)后訂閱的問(wèn)題.

代碼分析: 和RACSubject 的使用一毛一樣

    // 先發(fā)送信號(hào)
    [replaySubject sendNext:@10];
    
    // 后訂閱信號(hào)
    [replaySubject subscribeNext:^(id  _Nullable x) {
        // 可以正常打印
        NSLog(@"x = %@", x);
    }];

↓具體實(shí)現(xiàn)原理↓

  1. RACReplaySubject 對(duì)象創(chuàng)建的時(shí)候, 會(huì)在父類(lèi)的基礎(chǔ)之上多做一步,創(chuàng)建一個(gè)數(shù)組用來(lái)保存發(fā)送的數(shù)據(jù)(當(dāng)_subscribers 中所有訂閱者都成功發(fā)送了數(shù)據(jù), 那么就會(huì)刪除當(dāng)前要發(fā)送的數(shù)據(jù), 避免出現(xiàn)一個(gè)數(shù)據(jù)重復(fù)發(fā)送的問(wèn)題)
  2. 發(fā)送數(shù)據(jù): 當(dāng)有訂閱者訂閱時(shí),發(fā)送數(shù)據(jù); 沒(méi)有訂閱者訂閱時(shí)發(fā)送失敗, 就不發(fā)送,等待新的訂閱者.
  3. 訂閱信號(hào), 先遍歷一次保存數(shù)據(jù)的數(shù)組, 如果有就執(zhí)行第二步

.End

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末聋溜,一起剝皮案震驚了整個(gè)濱河市谆膳,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌撮躁,老刑警劉巖漱病,帶你破解...
    沈念sama閱讀 222,104評(píng)論 6 515
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異把曼,居然都是意外死亡缨称,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,816評(píng)論 3 399
  • 文/潘曉璐 我一進(jìn)店門(mén)祝迂,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)睦尽,“玉大人,你說(shuō)我怎么就攤上這事型雳〉狈玻” “怎么了?”我有些...
    開(kāi)封第一講書(shū)人閱讀 168,697評(píng)論 0 360
  • 文/不壞的土叔 我叫張陵纠俭,是天一觀的道長(zhǎng)沿量。 經(jīng)常有香客問(wèn)我,道長(zhǎng)冤荆,這世上最難降的妖魔是什么朴则? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 59,836評(píng)論 1 298
  • 正文 為了忘掉前任,我火速辦了婚禮钓简,結(jié)果婚禮上乌妒,老公的妹妹穿的比我還像新娘汹想。我一直安慰自己,他們只是感情好撤蚊,可當(dāng)我...
    茶點(diǎn)故事閱讀 68,851評(píng)論 6 397
  • 文/花漫 我一把揭開(kāi)白布古掏。 她就那樣靜靜地躺著,像睡著了一般侦啸。 火紅的嫁衣襯著肌膚如雪槽唾。 梳的紋絲不亂的頭發(fā)上,一...
    開(kāi)封第一講書(shū)人閱讀 52,441評(píng)論 1 310
  • 那天光涂,我揣著相機(jī)與錄音庞萍,去河邊找鬼。 笑死忘闻,一個(gè)胖子當(dāng)著我的面吹牛挂绰,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播服赎,決...
    沈念sama閱讀 40,992評(píng)論 3 421
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼葵蒂,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了重虑?” 一聲冷哼從身側(cè)響起践付,我...
    開(kāi)封第一講書(shū)人閱讀 39,899評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎缺厉,沒(méi)想到半個(gè)月后永高,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 46,457評(píng)論 1 318
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡提针,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,529評(píng)論 3 341
  • 正文 我和宋清朗相戀三年命爬,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片辐脖。...
    茶點(diǎn)故事閱讀 40,664評(píng)論 1 352
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡饲宛,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出嗜价,到底是詐尸還是另有隱情艇抠,我是刑警寧澤,帶...
    沈念sama閱讀 36,346評(píng)論 5 350
  • 正文 年R本政府宣布久锥,位于F島的核電站家淤,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏瑟由。R本人自食惡果不足惜絮重,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 42,025評(píng)論 3 334
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧青伤,春花似錦督怜、人聲如沸。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 32,511評(píng)論 0 24
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)痴施。三九已至擎厢,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間辣吃,已是汗流浹背动遭。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 33,611評(píng)論 1 272
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留神得,地道東北人厘惦。 一個(gè)月前我還...
    沈念sama閱讀 49,081評(píng)論 3 377
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像哩簿,于是被迫代替她去往敵國(guó)和親宵蕉。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,675評(píng)論 2 359