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

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"
    }];


在这种情况下,一切都会按预期进行,直到出现错误。如果发生错误,我会看到两个警报(一个有错误,另一个有“ Happy end”),但只希望有一个错误。

我知道为什么会这样


  错误会被内部信号自动捕获...等


但是我想要一些解决方案以达到理想的效果。

UPD:“ ...看到两个警报(一个出现错误,另一个出现“幸福的结局”)”

最佳答案

有两种可能的方法来实现所需的目标,具体取决于applyCommand的执行信号的行为。

如果它仅发送一个next值然后立即完成,则可以简单地使用switchToLatest运算符订阅该next值,并以“ Happy end”显示警报:

  [[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来解决,但我还没有尝试过。

09-04 23:40