RACCommand響應(yīng)結(jié)果解析

特別注意:定義的command中的封裝信號一定要sendCompleted;否則在生命周期內(nèi)無法被重新激活;

1. 普通的command

普通的RACCommand的使用很簡單了,只需要在封裝的信號中sendCompleted、sendError就可以。例如:

- (RACCommand *)commandForDataSelecting {
  if (!_commandForDataSelecting) {
    @weakify(self);
    _commandForDataSelecting = [[RACCommand alloc] initWithSignalBlock:^RACSignal *(id input) {
        return [[RACSignal createSignal:^RACDisposable *(id<RACSubscriber> subscriber) {
            @strongify(self);
            [[DBManager sharedDB] selectDataFromTabel:kCardInfoTableName forConditions:nil sucBlock:^(NSArray *datasSelected) {
                [subscriber sendCompleted];
            } errBlock:^(NSError *error) {
                [subscriber sendError:error];
            }];
            return nil;
        }] replayLast];
    }];
  }
  return _commandForDataSelecting;
}

2. 獲取響應(yīng)狀態(tài)

要處理的狀態(tài)有3種:開始,完成,失敗

  • 開始

    [[command executing] subscribeNext:^id(id x) {
        NSLog(@"數(shù)據(jù)加載中...");
    } // 或者在 'subscribeNext' 前面加上 'deliverOn:' 在主線程中處理;
    
  • 完成

    [[[command executionSignals] flattenMap:^ RACStream(RACSignal* innerSignal) {
        return [innerSignal materialize];
    }] subscribeNext:^(RACEvent* event) {
        if (event.eventType == RACEventTypeCompleted) {
            NSLog(@"數(shù)據(jù)加載完畢!"); // 1
        }
        else if (event.eventType == RACEventTypeError) {
            NSLog(@"數(shù)據(jù)加載失敗!"); //2
        }
        else if (event.eventType == RACEventTypeNext) {
            NSLog(@"數(shù)據(jù)加載中..."); //3
        }
    }];
    

實際測試發(fā)現(xiàn),subscribeNext只能獲取到 completed的狀態(tài),所以可以在 subscribeNext 前對結(jié)果進行過濾:filter:,過濾出completed的狀態(tài)。

  • 失敗

    [[command errors] subscribeNext:^(NSError* error) {
        NSLog(@"%@",[error localizedDescription]); //4
    }
    

3. 疑惑和解惑

  • 當(dāng)command能正常結(jié)束時,一切都沒問題??墒钱?dāng)command執(zhí)行異常時,不僅異常errors被拋出://4,completed也被拋出了//1
  • 如果上面 // 1-4 都用蒙版 MBProgressHUD 顯示的話,線程調(diào)度會有問題,蒙版顯示會一閃而過;

所以,我們要解決的目標(biāo):當(dāng) command 拋出 error 時,不要同時拋出 completed .

  • 解決方法
    command的定義中,將返回的RACSignal再次封裝materialize,封裝后產(chǎn)生的信號的值是RACEvent類型;
    然后executionSignals通過解封裝dematerialize出一個新的信號,對它進行'異常'、'完成'捕獲:subscribeError: completed:分別處理異常和完成狀態(tài).

新的command定義和executionSignals處理如下:

// command定義
- (RACCommand *)commandForDataSelecting {
  if (!_commandForDataSelecting) {
    @weakify(self);
    _commandForDataSelecting = [[RACCommand alloc] initWithSignalBlock:^RACSignal *(id input) {
        return [[[[RACSignal createSignal:^RACDisposable *(id<RACSubscriber> subscriber) {
            @strongify(self);
            [[DBManager sharedDB] selectDataFromTabel:kCardInfoTableName forConditions:nil sucBlock:^(NSArray *datasSelected) {
                self.cardInfosSelected = [datasSelected copy];
                [subscriber sendCompleted];
            } errBlock:^(NSError *error) {
                [subscriber sendError:error];
            }];
            return nil;
        }] replayLast] materialize] delay:1];
    }];
  }
  return _commandForDataSelecting;
}

 // 結(jié)果處理
 [command.executionSignals subscribeNext:^(RACSignal* signal) {
    @strongify(self);
    [[[signal dematerialize] deliverOn:[RACScheduler mainThreadScheduler]] subscribeError:^(NSError *error) {
        [self.progressHUD showFailWithText:[error localizedDescription] andDetailText:nil onCompletion:nil];
    } completed:^{
        [self.progressHUD showSuccessWithText:@"加載成功" andDetailText:nil onCompletion:^{}];
    }];
}];
最后編輯于
?著作權(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)容