4.RAC之RACMulticastConnection 連接類

在講RACMulticastConnection之前我們先來看一個例子醇蝴。

 // 1.創(chuàng)建信號
    RACSignal *signal = [RACSignal createSignal:^RACDisposable * _Nullable(id<RACSubscriber>  _Nonnull subscriber) {
        NSLog(@"請求網(wǎng)絡(luò)數(shù)據(jù)");
        
        // 3.成功獲取網(wǎng)絡(luò)返回的數(shù)據(jù)弃理,發(fā)送數(shù)據(jù)
        [subscriber sendNext:@"發(fā)送數(shù)據(jù)"];
        
        return nil;
    }];
    
    // 2.訂閱信號
    [signal subscribeNext:^(id  _Nullable x) {
        NSLog(@"訂閱者一 訂閱信號:%@",x);
    }];
    
    [signal subscribeNext:^(id  _Nullable x) {
        NSLog(@"訂閱者二 訂閱信號:%@",x);
    }];
    
    [signal subscribeNext:^(id  _Nullable x) {
        NSLog(@"訂閱者三 訂閱信號:%@",x);
    }];

打印結(jié)果
2017-05-31 19:12:06.220 RACDemo[1332:258342] 請求網(wǎng)絡(luò)數(shù)據(jù)
2017-05-31 19:12:06.221 RACDemo[1332:258342] 訂閱者一 訂閱信號:發(fā)送數(shù)據(jù)
2017-05-31 19:12:06.221 RACDemo[1332:258342] 請求網(wǎng)絡(luò)數(shù)據(jù)
2017-05-31 19:12:06.221 RACDemo[1332:258342] 訂閱者二 訂閱信號:發(fā)送數(shù)據(jù)
2017-05-31 19:12:06.221 RACDemo[1332:258342] 請求網(wǎng)絡(luò)數(shù)據(jù)
2017-05-31 19:12:06.222 RACDemo[1332:258342] 訂閱者三 訂閱信號:發(fā)送數(shù)據(jù)

你發(fā)現(xiàn)問題了嗎?
這里有一個問題,就是我們每次訂閱信號的時候色解,它都會去請求一次網(wǎng)絡(luò)數(shù)據(jù)茂嗓。
但實際上,我們并不需要這么頻繁的請求網(wǎng)絡(luò)數(shù)據(jù)科阎,我們只需要確保第一次拿到網(wǎng)絡(luò)返回的數(shù)據(jù)后述吸,在接下來的每一次訂閱中,直接拿到第一次獲取到的網(wǎng)絡(luò)數(shù)據(jù)就好了锣笨。

針對這種情況蝌矛,我們就可以使用 RACMulticastConnection.
不管訂閱多少次信號,只會請求一次網(wǎng)絡(luò)數(shù)據(jù)

RACMulticastConnection 使用例子

// 1. 創(chuàng)建信號
    RACSignal *signal = [RACSignal createSignal:^RACDisposable * _Nullable(id<RACSubscriber>  _Nonnull subscriber) {
        NSLog(@"請求網(wǎng)絡(luò)數(shù)據(jù)");
        // 成功獲取網(wǎng)絡(luò)返回的數(shù)據(jù)错英,發(fā)送數(shù)據(jù)
        [subscriber sendNext:@"發(fā)送網(wǎng)絡(luò)數(shù)據(jù)"];
        return nil;
    }];
// 2. 把信號轉(zhuǎn)換成連接類
// 這里除了用publish創(chuàng)建朴读,也可以用-muticast:方法創(chuàng)建
    RACMulticastConnection *connection = [signal publish];
// 3. 訂閱連接類的信號
    [connection.signal subscribeNext:^(id  _Nullable x) {
        NSLog(@"連接類訂閱者一 訂閱信號:%@",x);
    }];
    
    [connection.signal subscribeNext:^(id  _Nullable x) {
        NSLog(@"連接類訂閱者二 訂閱信號:%@",x);
    }];
    
    [connection.signal subscribeNext:^(id  _Nullable x) {
        NSLog(@"連接類訂閱者三 訂閱信號:%@",x);
    }];
// 4. 連接
    [connection connect];

打印結(jié)果:
2017-05-31 20:36:08.569 RACDemo[1645:604549] 請求網(wǎng)絡(luò)數(shù)據(jù)
2017-05-31 20:36:08.569 RACDemo[1645:604549] 連接類訂閱者一 訂閱信號:發(fā)送網(wǎng)絡(luò)數(shù)據(jù)
2017-05-31 20:36:08.569 RACDemo[1645:604549] 連接類訂閱者二 訂閱信號:發(fā)送網(wǎng)絡(luò)數(shù)據(jù)
2017-05-31 20:36:08.569 RACDemo[1645:604549] 連接類訂閱者三 訂閱信號:發(fā)送網(wǎng)絡(luò)數(shù)據(jù)

這樣子我們就解決了頻繁訪問網(wǎng)絡(luò)的問題。其實RACMulticastConnection主要就避免了多次調(diào)用創(chuàng)建信號中的block走趋。

接下來讓我們看看 RACMulticastConnection 底層是怎么實現(xiàn)的衅金。

  • 第一步創(chuàng)建RACSignal(原始信號)
RACSignal *signal = [RACSignal createSignal:^RACDisposable * _Nullable(id<RACSubscriber>  _Nonnull subscriber) {
 // block調(diào)用時刻:當RACMulticastConnection 調(diào)用 connect 方法的時候
// subscribe 此時的本質(zhì)是一個 RACSubject.
// RACSubject sendNext:  遍歷訂閱者數(shù)組,讓訂閱者數(shù)組里面的每一個訂閱者 都去調(diào)用他們的nextBlock簿煌。
// 上面三句看不懂氮唯,沒關(guān)系,記著姨伟,接著往下看

        NSLog(@"請求網(wǎng)絡(luò)數(shù)據(jù)");
        // 成功獲取網(wǎng)絡(luò)返回的數(shù)據(jù)惩琉,發(fā)送數(shù)據(jù)
        [subscriber sendNext:@"發(fā)送網(wǎng)絡(luò)數(shù)據(jù)"];
        return nil;
    }];
  • 第二步,將信號轉(zhuǎn)換成連接類RACMulticastConnection夺荒。首先通過[signal publish]在底層創(chuàng)建一個RACSubject,再把RACSubject和RACSignal保存到RACMulticastConnection中瞒渠,RACMulticastConnection中的_sourceSignal == RACSignal,_signal == RACSubject技扼。
// signal 是 RACSignal 信號類
RACMulticastConnection *connection = [signal publish];

 // RACSignal class
 - (RACMulticastConnection *)publish {
    // 創(chuàng)建一個 RACSubject 信號類
    RACSubject *subject = [[RACSubject subject] setNameWithFormat:@"[%@] -publish", self.name];
// 返回連接類  RACMulticastConnection
    RACMulticastConnection *connection = [self multicast:subject];
    return connection;
}
  - (RACMulticastConnection *)multicast:(RACSubject *)subject {
    [subject setNameWithFormat:@"[%@] -multicast: %@", self.name, subject.name];
// 創(chuàng)建連接類RACMulticastConnection伍玖,傳入一個RACSignal和一個RACSubject,self就是RACSignal
    RACMulticastConnection *connection = [[RACMulticastConnection alloc] initWithSourceSignal:self subject:subject];
    return connection;
}
 // RACMulticastConnection class
  - (instancetype)initWithSourceSignal:(RACSignal *)source subject:(RACSubject *)subject {
    NSCParameterAssert(source != nil);
    NSCParameterAssert(subject != nil);

    self = [super init];
//  _sourceSignal 是 RACSignal, _signal 是 RACSubject
    _sourceSignal = source;
    _serialDisposable = [[RACSerialDisposable alloc] init];
    _signal = subject;
    
    return self;
}
  • 第三步剿吻,訂閱連接類信號窍箍。
[connection.signal subscribeNext:^(id  _Nullable x) {
        NSLog(@"連接類訂閱者一 訂閱信號:%@",x);
    }];

上面說過了,connection.signal 中的signal就是RACSubject丽旅,在前兩章有說過椰棘,RACSubject訂閱信號的原理是 創(chuàng)建訂閱者,保存nextBlock,將創(chuàng)建的訂閱者存放到一個訂閱者數(shù)組里面中去榄笙。

  • 第四步邪狞,連接。[connection connect] 內(nèi)部會訂閱RACSignal(原始信號)茅撞,并且訂閱者是RACSubject帆卓。訂閱RACSignal杆逗,會調(diào)用第一步中的block。
  [connection connect];

  - (RACDisposable *)connect {
    BOOL shouldConnect = OSAtomicCompareAndSwap32Barrier(0, 1, &_hasConnected);

    if (shouldConnect) {
  // 重點這句鳞疲,self.sourceSignal 就是RACSignal,_signal就是RACSubject.
//此處RACSignal訂閱信號罪郊,訂閱者就是RACSubject
// 訂閱RACSignal,會調(diào)用第一步中創(chuàng)建信號的block尚洽。
        self.serialDisposable.disposable = [self.sourceSignal subscribe:_signal];
    }

    return self.serialDisposable;
}

總結(jié)

RACMulticastConnection 使用并不難悔橄,理解的話可能會有點繞。如果單純看我寫的可能會看不懂腺毫,建議自己去看下源碼癣疟,可能更好理解一點。
自己在這里繼續(xù)做下對RACMulticastConnection簡短的總結(jié)

 1.創(chuàng)建RACSignal(原始信號) + (RACSignal *)createSignal:(RACDisposable * (^)(id<RACSubscriber> subscriber))didSubscribe
 2.創(chuàng)建連接  RACMulticastConnection *connection = [signal publish];
 2-1  connection 里面就包含了兩個信號(sourceSignal,_signal)潮酒,一個是我們自己創(chuàng)建的RACSignal(原始信號),另外一個就是它在底層幫我們創(chuàng)建的RACSubject睛挚。
 3.訂閱connection.signal 信號,其實就是訂閱RACSubject信號急黎。創(chuàng)建訂閱者扎狱,訂閱者保存nextBlock,將訂閱者保存到一個數(shù)組中。
 4.連接[connection connect]勃教。
 4-1.訂閱RACSignal(原始信號)淤击,訂閱者就是RACSubject
 4-2.訂閱原始信號,就會調(diào)用原始信號中的didSubscribe
 4-3.在didSubscribe中故源,拿到訂閱者污抬,調(diào)用sendNext,其實是調(diào)用RACSubject的sendNext
 4-4.RACSubject調(diào)用sendNext绳军,其實就是會遍歷RACSubject所有訂閱者發(fā)送信號印机,調(diào)用它們保存的nextBlock.
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市门驾,隨后出現(xiàn)的幾起案子射赛,更是在濱河造成了極大的恐慌,老刑警劉巖猎唁,帶你破解...
    沈念sama閱讀 216,997評論 6 502
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件咒劲,死亡現(xiàn)場離奇詭異顷蟆,居然都是意外死亡诫隅,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,603評論 3 392
  • 文/潘曉璐 我一進店門帐偎,熙熙樓的掌柜王于貴愁眉苦臉地迎上來逐纬,“玉大人,你說我怎么就攤上這事削樊』砩” “怎么了兔毒?”我有些...
    開封第一講書人閱讀 163,359評論 0 353
  • 文/不壞的土叔 我叫張陵,是天一觀的道長甸箱。 經(jīng)常有香客問我育叁,道長,這世上最難降的妖魔是什么芍殖? 我笑而不...
    開封第一講書人閱讀 58,309評論 1 292
  • 正文 為了忘掉前任豪嗽,我火速辦了婚禮,結(jié)果婚禮上豌骏,老公的妹妹穿的比我還像新娘龟梦。我一直安慰自己,他們只是感情好窃躲,可當我...
    茶點故事閱讀 67,346評論 6 390
  • 文/花漫 我一把揭開白布计贰。 她就那樣靜靜地躺著,像睡著了一般蒂窒。 火紅的嫁衣襯著肌膚如雪躁倒。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,258評論 1 300
  • 那天洒琢,我揣著相機與錄音樱溉,去河邊找鬼。 笑死纬凤,一個胖子當著我的面吹牛福贞,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播停士,決...
    沈念sama閱讀 40,122評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼挖帘,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了恋技?” 一聲冷哼從身側(cè)響起拇舀,我...
    開封第一講書人閱讀 38,970評論 0 275
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎蜻底,沒想到半個月后骄崩,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,403評論 1 313
  • 正文 獨居荒郊野嶺守林人離奇死亡薄辅,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,596評論 3 334
  • 正文 我和宋清朗相戀三年要拂,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片站楚。...
    茶點故事閱讀 39,769評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡脱惰,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出窿春,到底是詐尸還是另有隱情拉一,我是刑警寧澤采盒,帶...
    沈念sama閱讀 35,464評論 5 344
  • 正文 年R本政府宣布,位于F島的核電站蔚润,受9級特大地震影響磅氨,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜嫡纠,卻給世界環(huán)境...
    茶點故事閱讀 41,075評論 3 327
  • 文/蒙蒙 一悍赢、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧货徙,春花似錦左权、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,705評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至蠢棱,卻和暖如春锌杀,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背泻仙。 一陣腳步聲響...
    開封第一講書人閱讀 32,848評論 1 269
  • 我被黑心中介騙來泰國打工糕再, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人玉转。 一個月前我還...
    沈念sama閱讀 47,831評論 2 370
  • 正文 我出身青樓突想,卻偏偏與公主長得像,于是被迫代替她去往敵國和親究抓。 傳聞我的和親對象是個殘疾皇子猾担,可洞房花燭夜當晚...
    茶點故事閱讀 44,678評論 2 354

推薦閱讀更多精彩內(nèi)容