当前位置: 代码迷 >> Ruby/Rails >> RACCommand 有sendError对executionSignals 如何破
  详细解决方案

RACCommand 有sendError对executionSignals 如何破

热度:170   发布时间:2016-04-29 02:18:43.0
RACCommand 有sendError对executionSignals 怎么破

RACCommand 一般我们都是放在ViewModel中,就像是一个Action,由用户或者View/ViewController的。
而且很多时候,我们不仅仅需要让这个action执行起来,而且还需要知道执行的结果。这里简单写个demo。
@interface ViewModel

  • (RACCommand*)testCommand; @end @implement ViewModel
  • (RACCommand*)testCommand{ return [RACCommand alloc] initWithSignalBlock:^RACSignal *(id input){ return [RACSignal createSignal:^RACDisposable *(id subscriber) { [subscribe sendError:[NSError errorWithDomain:@"" code:0 userInfo:nil]]; }]; //1 }]; @end

如果ViewController中是这么写的。
self.testBtn.rac_command = self.viewModel.testCommand;

现在有这样一个需要,就是知道这个command什么时候被执行了。执行的结果是咋样的,是否有错误,或者完成,那么应该怎么办呢。

之前我是这么写的。

[[self.testBtn.rac_command executing] subscribeNext:^(NSNumber *executing) {
if([executing boolValue]){
NSLog(@"正在执行"); //2
}
}];

[self.testBtn.rac_command.errors subscribeError:^(NSError *error)]{
NSLog(@"发生%@",error); //3
}];

[self.testBtn.rac_command.executionSignals flattenMap:^(RACSignal *exection){
return [[exection ignoreAll] concate:[RACSignal return:RACUnit.defaultUnit]]; //4
} subscribeNext:^(_){
NSLog(@"执行完毕"); //5
}];

感觉没有问题,但是实际的问题来。就是在viewModel中sendError得话,那么3的位置是能够执行到得,但是我不期望的5也被执行了。跟踪之后,发现原来RACCommand里面本身会对error进行catch的然后concate 返回一个error的signal了。所以4中本来应该发现error直接出去的都变成了普通的return signal了。

google一下吧,看看有什么好的解决办法。发现使用materialize 和dematerialize的规避吧。materialize回家所有的信号封装成event的形势出去。这样RACCommand就拿不到error了。也就是说2处也不会有了。只有在需要的地方也就是我们的ViewController中使用dematerialize出来拿到我们实际想要的数据了。

改动不大。在ViewModel中1处成
return [xxxxx materialize];

然后在ViewController中,将3部分代码可以去掉了。executionSignals 的部分需要改成
[self.testBtn.rac_command.executionSignals subscribeNext:^(RACSignal *execution) {
[[[execution dematerialize] deliverOn:[RACScheduler mainThreadScheduler]] subscribeError:^(NSError *error) {
NSLog(@"发生错误");
} completed:^{
NSLog(@"完成");
}];
}];

这样,所有你想要的东西都可以得到了。