RACCommand单独处理成功完成

时间:2015-07-14 17:50:38

标签: ios objective-c reactive-cocoa

我在实现一些逻辑简单代码时遇到问题。 简单来说,我想做这样的事情:

Complete command() {
    if (error) {
        show error alert
    }
    else {
        show "Happy ending" allert
    }
}

我知道如何制作第一部分,但第二部分我有问题

我的尝试:

[self.vm.applyCommand.errors subscribeNext:^(id x) {
    //Show alert with error
}];

[[[self.vm.applyCommand.executionSignals
    map:^(RACSignal *signal) {
        return [[signal ignoreValues] materialize];
    }]
    concat]
    subscribeNext:^(RACEvent *event) {
        //Show alert with "Happy end"
    }];

在这种情况下,一切都按预期工作,直到出现错误。如果出现错误,我会看到两个警告(一个有错误,另一个有"快乐结束"),但只想要一个有错误。

我知道为什么会这样,

  

错误将自动捕获到内部信号......等等

但我想要一些解决方案来做出理想的行为。

UPD:" ...参见两个提醒(一个有错误,另一个用#34;快乐结束")"

1 个答案:

答案 0 :(得分:1)

根据applyCommand的执行信号的行为方式,有两种方法可以实现您的目标。

如果它只发送一个next值,然后立即完成,您只需使用switchToLatest运算符即可订阅该next值并显示警告,其中包含' Happy end& #39;:

  [[self.command.executionSignals switchToLatest] subscribeNext:^(id x) {
    //Show alert with "Happy end"
  }];

否则它会复杂得多,因为很难区分RACCommand执行信号的成功完成和失败。如果出现错误,您将获得完成"调用RACEvent[[signal ignoreValues] materialize];,然后命令errors信号将错误发送为下一个值。

我设法使用命令executing信号执行此操作,该信号在@NO信号发送错误后发送errors 。您可以使用mergecombinePreviousWithStart:reduce运算符来检查命令是否因为发生错误而停止执行:

RACSignal *stoppedExecuting = [[self.vm.applyCommand.executing ignore:@YES] skip:1];
RACSignal *merged = [stoppedExecuting merge:self.vm.applyCommand.errors];

[[[merged combinePreviousWithStart:nil reduce:^id(id previous, id current) {
  return @( [previous isKindOfClass:[NSError class]] || [current isKindOfClass:[NSError class]] );
}] filter:^BOOL(NSNumber *errorOccurred) {
  return !errorOccurred.boolValue;
}] subscribeNext:^(id x) {
  NSLog(@"Happy end!");
}];

它不是一个完美的解决方案,因为它取决于从各种RACCommand信号发送值的顺序,这是一个实现细节,可以在将来改变(它对我有用)与RAC 2.5)。 我想这个问题可以用RAC 3.0来解决,因为它replaces RACCommand with Action,但我还没有尝试过。