RACSignal

文章系列
《ReactiveCocoa 概述》
《RACSignal》
《RACDisposable》
《RACSubject箱叁、RACReplaySubject(內(nèi)附冷信號和熱信號的區(qū)別)》
《集合RACTuple、RACSequence》
《RAC 中的通知、代理践磅、KVO, 基本事件杏瞻、方法的監(jiān)聽》
《rac_liftSelector》
《RACMulticastConnection》
《RACCommand》
《RAC - 核心方法bind》
《RAC - 定時器》
《RACScheduler》
《RAC - 點擊獲取驗證碼 demo》
《RAC - 映射(Map & flattenMap)》
《RAC信號操作解釋合集》
《RAC - 信號的生命周期》

RACSignal: 信號類, 本身不具備發(fā)送信號的能力, 當(dāng)被訂閱后, 用于傳遞改變的數(shù)據(jù), 可傳遞以下三種狀態(tài):

  • sendNext(id):可理解為傳遞正確數(shù)據(jù)平道,告訴訂閱者進(jìn)行下一步處理
  • sendError:傳遞的數(shù)據(jù)錯誤辅髓,告訴訂閱者錯誤處理
  • sendCompleted:告訴訂閱者已完成
  • 流程圖:
    signal.png
  • 代碼分析 (注釋很詳細(xì)!!!)

- (void)signalTest {
    
    /* 1. 創(chuàng)建信號 signal
            - 通過 createSignal: 方法創(chuàng)建,其參數(shù)為一個返回值位RACDisposable 類型的block (didSubcribe)
     */
    RACSignal *signal = [RACSignal createSignal:^RACDisposable * _Nullable(id<RACSubscriber>  _Nonnull subscriber) {
        
        // 2. 通過block 傳入的訂閱者subscriber 來發(fā)送信息
        [subscriber sendNext:@10];
        
        // sendError浪感、sendCompleted 二者只能發(fā)送其一,  就代表結(jié)束了.
        [subscriber sendError:[NSError errorWithDomain:@"錯誤" code:1001 userInfo:nil]];
        [subscriber sendCompleted];
        // 這里需要返回一個RACDisposable 類型的對象, 用于提前結(jié)束訂閱等操作, 一般無特殊需求, 返回nil 即可.
        return nil;
    }];
    
    /* 3. 訂閱者 (subscriber)
            - subscribeNext + error + completed 組合起來就是訂閱者
            - 一旦訂閱者訂閱了信號消息, 就會執(zhí)行上面的didSubcribe 的block.
     */
    [signal subscribeNext:^(id  _Nullable x) {
        NSLog(@"%@", x);
    } error:^(NSError * _Nullable error) {
        NSLog(@"ERROR=%@", error);
    } completed:^{
        NSLog(@"完成");
    }];
}
  • ↓分析 [RACSignal createSignal:]內(nèi)部實現(xiàn)↓:
// 第1次點擊方法跳轉(zhuǎn)內(nèi)部實現(xiàn):
+ (RACSignal *)createSignal:(RACDisposable * (^)(id<RACSubscriber> subscriber))didSubscribe {
    // 內(nèi)部創(chuàng)建RACDynamicSignal 信號, 并將外部block 繼續(xù)傳遞
    return [RACDynamicSignal createSignal:didSubscribe];
}

// 第2次點擊方法跳轉(zhuǎn)內(nèi)部實現(xiàn):
+ (RACSignal *)createSignal:(RACDisposable * (^)(id<RACSubscriber> subscriber))didSubscribe {
    // 1. 創(chuàng)建 RACDynamicSignal對象
    // 2. 保存以參數(shù)形式傳遞進(jìn)來的 block
    // 3. 返回 RACDynamicSignal 對象
    RACDynamicSignal *signal = [[self alloc] init];
    signal->_didSubscribe = [didSubscribe copy];
    return [signal setNameWithFormat:@"+createSignal:"];
}
  • ↓分析 訂閱者 訂閱過程的實現(xiàn)(源碼邏輯分析, 幫助理解)↓:
    // 開始訂閱
    [signal subscribeNext:^(id  _Nullable x) {
        // 訂閱信號之后得到帶有一個參數(shù)為 x的 block
        NSLog(@"%@", x);
    }];
// 點擊 [signal subscribeNext:]內(nèi)部實現(xiàn)
- (RACDisposable *)subscribeNext:(void (^)(id x))nextBlock {
    NSCParameterAssert(nextBlock != NULL);
    // 創(chuàng)建訂閱者 o
    RACSubscriber *o = [RACSubscriber subscriberWithNext:nextBlock error:NULL completed:NULL];
    return [self subscribe:o];
}

// 點擊[RACSubscriber subscriberWithNext:] 內(nèi)部實現(xiàn)
+ (instancetype)subscriberWithNext:(void (^)(id x))next error:(void (^)(NSError *error))error completed:(void (^)(void))completed {
    // 1. 創(chuàng)建訂閱者對象
    RACSubscriber *subscriber = [[self alloc] init];
    // 2. 保存Next block 缎罢、error block 伊群、completed block
    subscriber->_next = [next copy];
    subscriber->_error = [error copy];
    subscriber->_completed = [completed copy];
    // 3. 返回訂閱者
    return subscriber;
}

// 點擊[self subscribe:o] 內(nèi)部實現(xiàn)
- (RACDisposable *)subscribe:(id<RACSubscriber>)subscriber {
    NSCParameterAssert(subscriber != nil);

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

    // 4. 這里判斷didSubcribe是 否為空
    // didSubcribe 對象就是signal 的block 對象
    if (self.didSubscribe != NULL) {
        RACDisposable *schedulingDisposable = [RACScheduler.subscriptionScheduler schedule:^{

            // 這里就在調(diào)用didSubscribe 方法,并且把剛傳入的 subscriber 調(diào)用出去
            // 5. 也就是說, 要執(zhí)行 signal對象創(chuàng)建方法的 block
            RACDisposable *innerDisposable = self.didSubscribe(subscriber);
            [disposable addDisposable:innerDisposable];
        }];

        [disposable addDisposable:schedulingDisposable];
    }
    
    return disposable;
}
  • 通過注釋5 可以知道, 接下來就會調(diào)用[subscriber sendNext:@10] 等操作, 這也就是信號的發(fā)送.
    ↓sendNext 源碼↓
- (void)sendNext:(id)value {
    @synchronized (self) {
        void (^nextBlock)(id) = [self.next copy];
        // 6. nextblock 不為空就把傳進(jìn)來傳value 原封不動的調(diào)用出去, 而這個nextblock就是我們在訂閱信號的時候創(chuàng)建的那個subscriber 所保存的nextblock
        if (nextBlock == nil) return;

        nextBlock(value);
    }
}
  • 通過注釋6 可以知道, 信號通過send 操作, 回調(diào)出來, 進(jìn)行打印.
    [signal subscribeNext:^(id  _Nullable x) {
        // 打印 x
        NSLog(@"%@", x);
    }];

總結(jié):

所以RACSignal的處理流程就是

創(chuàng)建信號的block會在訂閱信號的時候調(diào)用
訂閱信號的block會在訂閱者發(fā)布信息的時候調(diào)用

.End

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末策精,一起剝皮案震驚了整個濱河市舰始,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌咽袜,老刑警劉巖丸卷,帶你破解...
    沈念sama閱讀 222,000評論 6 515
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異询刹,居然都是意外死亡谜嫉,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,745評論 3 399
  • 文/潘曉璐 我一進(jìn)店門凹联,熙熙樓的掌柜王于貴愁眉苦臉地迎上來沐兰,“玉大人,你說我怎么就攤上這事蔽挠∽〈常” “怎么了?”我有些...
    開封第一講書人閱讀 168,561評論 0 360
  • 文/不壞的土叔 我叫張陵澳淑,是天一觀的道長比原。 經(jīng)常有香客問我,道長杠巡,這世上最難降的妖魔是什么量窘? 我笑而不...
    開封第一講書人閱讀 59,782評論 1 298
  • 正文 為了忘掉前任,我火速辦了婚禮忽孽,結(jié)果婚禮上绑改,老公的妹妹穿的比我還像新娘谢床。我一直安慰自己,他們只是感情好厘线,可當(dāng)我...
    茶點故事閱讀 68,798評論 6 397
  • 文/花漫 我一把揭開白布识腿。 她就那樣靜靜地躺著,像睡著了一般造壮。 火紅的嫁衣襯著肌膚如雪渡讼。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 52,394評論 1 310
  • 那天,我揣著相機與錄音,去河邊找鬼殿衰。 笑死燎窘,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的游添。 我是一名探鬼主播,決...
    沈念sama閱讀 40,952評論 3 421
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼皂贩!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起昆汹,我...
    開封第一講書人閱讀 39,852評論 0 276
  • 序言:老撾萬榮一對情侶失蹤明刷,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后满粗,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體辈末,經(jīng)...
    沈念sama閱讀 46,409評論 1 318
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 38,483評論 3 341
  • 正文 我和宋清朗相戀三年映皆,在試婚紗的時候發(fā)現(xiàn)自己被綠了挤聘。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 40,615評論 1 352
  • 序言:一個原本活蹦亂跳的男人離奇死亡劫扒,死狀恐怖檬洞,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情沟饥,我是刑警寧澤添怔,帶...
    沈念sama閱讀 36,303評論 5 350
  • 正文 年R本政府宣布,位于F島的核電站贤旷,受9級特大地震影響广料,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜幼驶,卻給世界環(huán)境...
    茶點故事閱讀 41,979評論 3 334
  • 文/蒙蒙 一艾杏、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧盅藻,春花似錦购桑、人聲如沸畅铭。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,470評論 0 24
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽硕噩。三九已至,卻和暖如春缭贡,著一層夾襖步出監(jiān)牢的瞬間炉擅,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,571評論 1 272
  • 我被黑心中介騙來泰國打工阳惹, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留谍失,地道東北人。 一個月前我還...
    沈念sama閱讀 49,041評論 3 377
  • 正文 我出身青樓莹汤,卻偏偏與公主長得像快鱼,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子体啰,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 45,630評論 2 359