ReactiveCocoa學(xué)習(xí)筆記整理(三)

此文章是針對ReactiveCocoa的學(xué)習(xí)總結(jié)整理,該文是第三篇。我們這篇主要講解一下RACCommand以及RAC替換UIKit的典型例子。未閱讀前兩篇的童鞋,吶,給你傳送門。

五. RACCommand的基本簡介跟使用

1. RACCommand簡介以及使用

RACCommand是RAC中用于處理事件的類,我們可以把事件如何處理,事件中的數(shù)據(jù)如何傳遞,包裝到這個類中。使用這個類可以很方便的監(jiān)控事件的執(zhí)行過程。RACCommand的使用步驟可以總結(jié)為以下三點:

  1. 創(chuàng)建命令 initWithSignalBlock:(RACSignal * (^)(id input))signalBlock
  2. 在signalBlock中,創(chuàng)建RACSignal,并且作為signalBlock的返回值
  3. 執(zhí)行命令 -(RACSignal * )execute:(id)input
    在RAC的開發(fā)中,我們通常會把網(wǎng)絡(luò)請求封裝到RACCommand,直接執(zhí)行某個RACCommand就能發(fā)送請求。然后當(dāng)RACCommand內(nèi)部請求到數(shù)據(jù)的時候,需要把請求的數(shù)據(jù)傳遞給外界,這時候就需要通過signalBlock返回的信號傳遞了。
    那么我們?nèi)绾文玫絉ACCommand中返回信號發(fā)出的數(shù)據(jù)?
  • RACCommand有個執(zhí)行信號源executionSignals,這個是signal of signals(信號的信號),意思是信號發(fā)出的數(shù)據(jù)是信號,不是普通的類型。
  • 訂閱executionSignals就能拿到RACCommand中返回的信號,然后訂閱signalBlock返回的信號,就能獲取發(fā)出的值。

在RACCommand的使用過程中,我們及其要注意以下的幾點事項:

  • signalBlock必須要返回一個信號,不能傳nil
  • 如果不想要傳遞信號,直接創(chuàng)建空的信號[RACSignal empty]
  • RACCommand中信號如果數(shù)據(jù)傳遞完,必須調(diào)用[subscriber sendCompleted],這時命令才會執(zhí)行完畢,否則永遠處于執(zhí)行中
  • RACCommand需要被強引用,否則接收不到RACCommand中的信號,因此RACCommand中的信號是延遲發(fā)送的
    好了,大致了解了RACCommand的基本概念以及使用步驟之后,我們通過簡單的小實例來看一下RACCommand怎樣使用,接下來,我們模擬一下監(jiān)聽按鈕點擊,發(fā)送網(wǎng)絡(luò)請求的過程,請看代碼:
    // 1.創(chuàng)建命令
    RACCommand *command=[[RACCommand alloc] initWithSignalBlock:^RACSignal *(id input) {
        NSLog(@"執(zhí)行命令");
        
        // 創(chuàng)建空信號,必須返回信號
        //        return [RACSignal empty];
        
        // 2.創(chuàng)建信號,用來傳遞數(shù)據(jù)
        return [RACSignal createSignal:^RACDisposable *(id<RACSubscriber> subscriber) {
            
            [subscriber sendNext:@"請求數(shù)據(jù)"];
            
            // 注意:數(shù)據(jù)傳遞完,最好調(diào)用sendCompleted,這時命令才執(zhí)行完畢。
            [subscriber sendCompleted];
            return nil;
        }];
    }];
    
    // 強引用命令,不要被銷毀,否則接收不到數(shù)據(jù)
    _conmmand = command;
    
    // 3.訂閱RACCommand中的信號
    [command.executionSignals subscribeNext:^(id x) {
        
        [x subscribeNext:^(id x) {
            
            NSLog(@"executionSignals:%@",x);
        }];
    }];
    
    // RAC高級用法
    // switchToLatest:用于signal of signals,獲取signal of signals發(fā)出的最新信號,也就是可以直接拿到RACCommand中的信號
    [command.executionSignals.switchToLatest subscribeNext:^(id x) {
        
        NSLog(@"executionSignals.switchToLatest:%@",x);
    }];
    
    // 4.監(jiān)聽命令是否執(zhí)行完畢,默認會來一次,可以直接跳過,skip表示跳過第一次信號。
    [[command.executing skip:1] subscribeNext:^(id x) {
        
        if ([x boolValue] == YES) {
            // 正在執(zhí)行
            NSLog(@"正在執(zhí)行");
            
        }else{
            // 執(zhí)行完成
            NSLog(@"執(zhí)行完成");
        }
        
    }];
    // 5.執(zhí)行命令
    [self.conmmand execute:@1];
    
    
//    輸出
//    執(zhí)行命令
//    正在執(zhí)行
//    executionSignals:請求數(shù)據(jù)
//    executionSignals.switchToLatest:請求數(shù)據(jù)
//    執(zhí)行完成

上述代碼就是使用RACCommand模擬的點擊按鈕進行網(wǎng)絡(luò)請求的過程,可以看出,RACCommand可以很方便的處理事件以及事件中的數(shù)據(jù)傳遞。

2.RACMulticastConnection的使用

講到了RACCommand,那么必不可少的有按鈕的多次點擊導(dǎo)致多次網(wǎng)絡(luò)請求的問題。RACMulticastConnection用于當(dāng)一個信號,被多次訂閱時,為了保證創(chuàng)建信號時,避免多次調(diào)用創(chuàng)建信號中的block,造成副作用,可以使用這個類處理。首先,我們看一下RACMulticastConnection的使用步驟:

  1. 創(chuàng)建信號 + (RACSignal *)createSignal:(RACDisposable * (^)(id<RACSubscriber> subscriber))didSubscribe
  2. 創(chuàng)建連接 RACMulticastConnection *connect = [signal publish];
  3. 訂閱信號,注意:訂閱的不在是之前的信號,而是連接的信號。 [connect.signal subscribeNext:nextBlock]
  4. 連接 [connect connect]

然后我們看一下RACMulticastConnection的底層實現(xiàn)原理:

  • 創(chuàng)建connect,connect.sourceSignal -> RACSignal(原始信號) connect.signal -> RACSubject
  • 訂閱connect.signal,會調(diào)用RACSubject的subscribeNext,創(chuàng)建訂閱者,而且把訂閱者保存起來,不會執(zhí)行block
  • [connect connect]內(nèi)部會訂閱RACSignal(原始信號),并且訂閱者是RACSubject
    訂閱原始信號,就會調(diào)用原始信號中的didSubscribe
    didSubscribe,拿到訂閱者調(diào)用sendNext,其實是調(diào)用RACSubject的sendNext
  • RACSubject的sendNext,會遍歷RACSubject所有訂閱者發(fā)送信號
    因為剛剛第二步,都是在訂閱RACSubject,因此會拿到第二步所有的訂閱者,調(diào)用他們的nextBlock
    最后,我們通過簡單的小需求來實際使用一下。假設(shè)在一個信號中發(fā)送請求,每次訂閱一次都會發(fā)送請求,這樣就會導(dǎo)致多次請求。我們需要使用RACMulticastConnection解決這個問題。
  // 1.創(chuàng)建請求信號
    RACSignal *aSignal = [RACSignal createSignal:^RACDisposable *(id<RACSubscriber> subscriber) {
        
        
        NSLog(@"aSignal發(fā)送請求");
        
        return nil;
    }];
    // 2.訂閱信號
    [aSignal subscribeNext:^(id x) {
        
        NSLog(@"接收數(shù)據(jù)");
        
    }];
    // 2.訂閱信號
    [aSignal subscribeNext:^(id x) {
        
        NSLog(@"接收數(shù)據(jù)");
        
    }];
    
    // 3.運行結(jié)果,會執(zhí)行兩遍發(fā)送請求,也就是每次訂閱都會發(fā)送一次請求
 
    // RACMulticastConnection:解決重復(fù)請求問題
    // 1.創(chuàng)建信號
    RACSignal *signal = [RACSignal createSignal:^RACDisposable *(id<RACSubscriber> subscriber) {
        
        
        NSLog(@"signal發(fā)送請求");
        [subscriber sendNext:@1];
        
        return nil;
    }];
    
    // 2.創(chuàng)建連接
    RACMulticastConnection *connect = [signal publish];
    
    // 3.訂閱信號,
    // 注意:訂閱信號,也不能激活信號,只是保存訂閱者到數(shù)組,必須通過連接,當(dāng)調(diào)用連接,就會一次性調(diào)用所有訂閱者的sendNext:
    [connect.signal subscribeNext:^(id x) {
        
        NSLog(@"訂閱者一信號");
        
    }];
    
    [connect.signal subscribeNext:^(id x) {
        
        NSLog(@"訂閱者二信號");
        
    }];
    
    // 4.連接,激活信號
    [connect connect];
    
    
    
    //輸出
    //aSignal發(fā)送請求
    //aSignal發(fā)送請求
    
    
    //signal發(fā)送請求
    //訂閱者一信號
    //訂閱者二信號

通過以上的代碼,可以明確的看出, aSignal被執(zhí)行的兩次,雖然有兩個訂閱者 ,但其實只要執(zhí)行一次就可以。使用RACMulticastConnection我們解決了這個問題。
截止此文,RAC的筆記就先到這吧,其實RAC還有很多高階用法以及更大的發(fā)揮空間,剩下的就由你們自己去慢慢發(fā)掘吧。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容