如何使用ReactiveCocoa

时间:2017-08-16 11:16:18

标签: ios objective-c reactive-cocoa

我有一种情况,我想将特定原点信号中的事件分成两个信号,一个立即发射事件,另一个发射事件延迟3秒。其余的原始事件总是立即发出新事件。 但是如果在发出延迟事件之前新事件到达原点信号,则应该丢弃延迟事件。

像这样的事情 enter image description here

我将每个原始信号映射到 CS1(对于立即发射的事件),并将原始信号的特定事件过滤到 CS2(对于延迟发射的事件)enter image description here enter image description here

然后我将 CS1 CS2 合并到 CS3 ,这不会丢弃 S2

所以,我的问题是如何丢弃或取消S2,如何在不使用额外临时变量的情况下使用RAC实现这种情况?

ReactiveCocoa 2.x 当前代码

RACSignal* origin = …    
RACSignal* CS1 = [origin map:^id _Nullable(id  _Nullable value) {
        return @(YES);
    }];
RACSignal* CS2 = [[[origin filter:^BOOL(id  _Nullable value) {
        return [RACSignal empty];
    }] delay:3] map:^id _Nullable(id  _Nullable value) {
        return @(NO);
    }];
RACSignal* CS3 = [RACSignal merge:@[CS1, CS2]];

1 个答案:

答案 0 :(得分:1)

与实际问题无关的一句话:filter如果要发送元素,则应返回YES的bool;如果要过滤掉该元素,则返回NO

对于实际问题:

问题的解决方案是使用takeUntil。但是,如果您将takeUntil直接应用于CS2,则CS2作为一个整体将在事件到达CS1时立即取消。

解决方案是使用flatMap为延迟元素构建新的RACSignal,然后在内部信号上使用takeUntil

为了清晰起见,我已将单个步骤拆分为多个临时信号(我还更改了mapfilter所以我可以看到在尝试我的示例时发生的更好的事情,你应该很容易能够在那里使用你正确的功能):

RACSignal* CS1 = [self.origin map:^id _Nullable(NSNumber * _Nullable value) {
  return value;
}];

RACSignal *filtered = [self.origin filter:^BOOL(NSNumber * _Nullable value) {
  return (value.integerValue % 2) == 0;
}];

RACSignal *delayed = [filtered flattenMap:^__kindof RACSignal * _Nullable(id  _Nullable value) {
  // Build a new signal that returns just this one value,
  // but delayed and only if no event arrives on CS1
  return [[[RACSignal return:value]
           delay:3]
          takeUntil:CS1];
}];

RACSignal* CS2 = [delayed map:^id _Nullable(NSNumber * _Nullable value) {
  return @(-value.integerValue);
}] ;


RACSignal* CS3 = [RACSignal merge:@[CS1, CS2]];

您可以轻松地将其折叠回两个信号

RACSignal *CS2 = [[[self.origin filter:^BOOL(NSNumber * _Nullable value) {
  return (value.integerValue % 2) == 0;
}] flattenMap:^__kindof RACSignal * _Nullable(id  _Nullable value) {
  // Build a new signal that returns just this one value,
  // but delayed and only if no event arrives on CS1 before
  return [[[RACSignal return:value]
           delay:3]
          takeUntil:CS1];
}] map:^id _Nullable(NSNumber * _Nullable value) {
  return @(-value.integerValue);
}];

我已创建a sample project on github来演示解决方案。