ReactiveCocoa源碼分析02 -- RACCommand

RACCommand
  • RACCommand:是對(duì)一個(gè)動(dòng)作的觸發(fā)條件以及它產(chǎn)生的觸發(fā)事件的封裝,最常見(jiàn)的使用場(chǎng)景為:點(diǎn)擊按鈕,發(fā)送一個(gè)網(wǎng)絡(luò)請(qǐng)求;
    • 觸發(fā)條件:初始化RACCommand的入?yún)?code>enabledSignal就決定了RACCommand是否能開(kāi)始執(zhí)行,入?yún)nabledSignal就是觸發(fā)條件柄慰,舉個(gè)例子,一個(gè)按鈕是否能點(diǎn)擊税娜,是否能觸發(fā)點(diǎn)擊事情坐搔,就由入?yún)nabledSignal決定;
    • 觸發(fā)事件:初始化RACCommand的另外一個(gè)入?yún)?code>(RACSignal * (^)(id input))signalBlock就是對(duì)觸發(fā)事件的封裝敬矩,RACCommand每次執(zhí)行都會(huì)調(diào)用一次signalBlock閉包概行;
  • RACCommand內(nèi)部存在四個(gè)信號(hào)屬性,分別為:executionSignals弧岳,executing凳忙,enabled业踏,errors,在RACCommand的構(gòu)造函數(shù)initWithSignalBlock中會(huì)對(duì)以上四個(gè)信號(hào)進(jìn)行初始化涧卵,下面對(duì)它們進(jìn)行詳細(xì)介紹勤家;
  • executionSignals:是RACCommand 中最重要的信號(hào),從類(lèi)型上來(lái)看柳恐,它是一個(gè)包含信號(hào)的信號(hào)(高階信號(hào))伐脖,在每次執(zhí)行execute: 方法時(shí),最終都會(huì)向 executionSignals 中傳入一個(gè)最新的信號(hào)乐设;
_executionSignals = [[[self.addedExecutionSignalsSubject
        map:^(RACSignal *signal) {
            return [signal catchTo:[RACSignal empty]];
        }]
        deliverOn:RACScheduler.mainThreadScheduler]
        setNameWithFormat:@"%@ -executionSignals", self];
  • 將信號(hào)中所有錯(cuò)誤轉(zhuǎn)換成RACEmptySignal空信號(hào)對(duì)象讼庇,并派發(fā)到主線(xiàn)程;
  • executing:表示RACCommand中是否有正在執(zhí)行任務(wù)的信號(hào)近尚;
_executing = [[[[[immediateExecuting
        deliverOn:RACScheduler.mainThreadScheduler]
        // This is useful before the first value arrives on the main thread.
        startWith:@NO]
        distinctUntilChanged]
        replayLast]
        setNameWithFormat:@"%@ -executing", self];
  • enabled:表示RACCommand命令是否可以再次被執(zhí)行的信號(hào)巫俺,此信號(hào)依賴(lài)于另一個(gè)私有信號(hào)immediateEnabled
_immediateEnabled = [[[[RACSignal
        combineLatest:@[ enabledSignal, moreExecutionsAllowed ]]
        and]
        takeUntil:self.rac_willDeallocSignal]
        replayLast];
    
    _enabled = [[[[[self.immediateEnabled
        take:1]
        concat:[[self.immediateEnabled skip:1] deliverOn:RACScheduler.mainThreadScheduler]]
        distinctUntilChanged]
        replayLast]
        setNameWithFormat:@"%@ -enabled", self];
  • errors:是RACCommand中錯(cuò)誤信號(hào)肿男;
RACMulticastConnection *errorsConnection = [[[self.addedExecutionSignalsSubject
        flattenMap:^(RACSignal *signal) {
            return [[signal
                ignoreValues]
                catch:^(NSError *error) {
                    return [RACSignal return:error];
                }];
        }]
        deliverOn:RACScheduler.mainThreadScheduler]
        publish];
    
    _errors = [errorsConnection.signal setNameWithFormat:@"%@ -errors", self];
    [errorsConnection connect];
  • 從上一篇的內(nèi)容我們知道信號(hào)的使用步驟為:創(chuàng)建信號(hào),訂閱信號(hào)却嗡,發(fā)送信號(hào)內(nèi)容舶沛,訂閱者接收到信號(hào)內(nèi)容,核心部分為信號(hào)窗价,此信號(hào)是一階信號(hào)如庭,若創(chuàng)建的信號(hào)為二階信號(hào),那么發(fā)送的信號(hào)內(nèi)容就是一階信號(hào)撼港,此一階信號(hào)也是能被訂閱的坪它,下面提供一段RACCommand使用的測(cè)試代碼:
@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    
    RACCommand *command = [[RACCommand alloc]initWithSignalBlock:^RACSignal * _Nonnull(id  _Nullable input) {
        NSLog(@"執(zhí)行1");
        //創(chuàng)建一個(gè)一階信號(hào) 此信號(hào)會(huì)傳遞給RACCommand內(nèi)部屬性executionSignals
        RACSignal *signal = [RACSignal createSignal:^RACDisposable * _Nullable(id<RACSubscriber>  _Nonnull subscriber) {
            NSLog(@"執(zhí)行3");
            [subscriber sendNext:input];
            return nil;
        }];
        return signal;
    }];
    
    //一階信號(hào) -- 信號(hào)內(nèi)容(具象數(shù)據(jù))
    //二階信號(hào) -- 信號(hào)內(nèi)容(一階信號(hào))
    //command.executionSignals是一個(gè)高階信號(hào)
    //訂閱command的executionSignals信號(hào)
    [command.executionSignals subscribeNext:^(id  _Nullable x) {
        //x是接收的信號(hào)內(nèi)容 是一個(gè)一階信號(hào)
        [x subscribeNext:^(id  _Nullable x) {
           NSLog(@"執(zhí)行4");
           NSLog(@"接收數(shù)據(jù) -- %@",x);
        }];
        NSLog(@"執(zhí)行2");
    }];
    
    //訂閱command的executing信號(hào)
    [command.executing subscribeNext:^(NSNumber * _Nullable x) {
        NSLog(@"executing == %@",x);
    }];

    //訂閱command的error信號(hào)
    [command.errors subscribeNext:^(NSError * _Nullable x) {
        NSLog(@"errors == %@",x);
    }];

    [command execute:@"發(fā)送消息"];
}
@end
  • 測(cè)試結(jié)果如下:
image.png
  • 第一步:創(chuàng)建RACCommand命令,同時(shí)傳入?yún)?shù)block代碼塊帝牡;
image.png
  • 構(gòu)造方法中會(huì)對(duì)RACCommand的四種信號(hào)進(jìn)行初始化往毡;
  • 第二步:RACCommand命令執(zhí)行execute方法,內(nèi)部會(huì)調(diào)用保存的block代碼塊靶溜;
image.png
  • 整體的邏輯流程如下所示:
image.png
  • 其中二階信號(hào)executionSignals的創(chuàng)建實(shí)在RACCommand的構(gòu)造函數(shù)中开瞭;
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市罩息,隨后出現(xiàn)的幾起案子嗤详,更是在濱河造成了極大的恐慌,老刑警劉巖瓷炮,帶你破解...
    沈念sama閱讀 216,324評(píng)論 6 498
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件葱色,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡娘香,警方通過(guò)查閱死者的電腦和手機(jī)苍狰,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,356評(píng)論 3 392
  • 文/潘曉璐 我一進(jìn)店門(mén)办龄,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人舞痰,你說(shuō)我怎么就攤上這事土榴。” “怎么了响牛?”我有些...
    開(kāi)封第一講書(shū)人閱讀 162,328評(píng)論 0 353
  • 文/不壞的土叔 我叫張陵玷禽,是天一觀的道長(zhǎng)。 經(jīng)常有香客問(wèn)我呀打,道長(zhǎng)矢赁,這世上最難降的妖魔是什么? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 58,147評(píng)論 1 292
  • 正文 為了忘掉前任贬丛,我火速辦了婚禮撩银,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘豺憔。我一直安慰自己额获,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,160評(píng)論 6 388
  • 文/花漫 我一把揭開(kāi)白布恭应。 她就那樣靜靜地躺著抄邀,像睡著了一般。 火紅的嫁衣襯著肌膚如雪昼榛。 梳的紋絲不亂的頭發(fā)上境肾,一...
    開(kāi)封第一講書(shū)人閱讀 51,115評(píng)論 1 296
  • 那天,我揣著相機(jī)與錄音胆屿,去河邊找鬼奥喻。 笑死,一個(gè)胖子當(dāng)著我的面吹牛非迹,可吹牛的內(nèi)容都是我干的环鲤。 我是一名探鬼主播,決...
    沈念sama閱讀 40,025評(píng)論 3 417
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼憎兽,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼楔绞!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起唇兑,我...
    開(kāi)封第一講書(shū)人閱讀 38,867評(píng)論 0 274
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤酒朵,失蹤者是張志新(化名)和其女友劉穎,沒(méi)想到半個(gè)月后扎附,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體蔫耽,經(jīng)...
    沈念sama閱讀 45,307評(píng)論 1 310
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,528評(píng)論 2 332
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了匙铡。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片图甜。...
    茶點(diǎn)故事閱讀 39,688評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖鳖眼,靈堂內(nèi)的尸體忽然破棺而出黑毅,到底是詐尸還是另有隱情,我是刑警寧澤钦讳,帶...
    沈念sama閱讀 35,409評(píng)論 5 343
  • 正文 年R本政府宣布矿瘦,位于F島的核電站,受9級(jí)特大地震影響愿卒,放射性物質(zhì)發(fā)生泄漏缚去。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,001評(píng)論 3 325
  • 文/蒙蒙 一琼开、第九天 我趴在偏房一處隱蔽的房頂上張望易结。 院中可真熱鬧,春花似錦柜候、人聲如沸搞动。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 31,657評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)滋尉。三九已至,卻和暖如春飞主,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背高诺。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 32,811評(píng)論 1 268
  • 我被黑心中介騙來(lái)泰國(guó)打工碌识, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人虱而。 一個(gè)月前我還...
    沈念sama閱讀 47,685評(píng)論 2 368
  • 正文 我出身青樓筏餐,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親牡拇。 傳聞我的和親對(duì)象是個(gè)殘疾皇子魁瞪,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,573評(píng)論 2 353

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