特別注意:定義的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:^{}];
}];
}];