5

我有两个RACSignal,其中一个是计时器,另一个表示有工作要做。由于工作指示有时不可靠,因此有计时器,它负责在精确通知不起作用时定期完成工作。

一般设置是:

    RACSignal *signal = [RACSignal merge:@[
                         [[RACSignal interval:0.5 onScheduler:[RACScheduler scheduler]]
                           filter:^BOOL(__unused id _x) {
                               return isThereAProblemInDeliveringWork();
                           }],
                         incomingWorkSubject
                         ]];

现在我想signal一完成就incomingWorkSubject完成。所以,一般来说:只要它的任何输入信号完成,就完成合并的信号。不幸的是,[RACSignal merge:...]没有做我想做的事,显然是在等待所有传入的信号完成。

实现这一目标的 ReactiveCocoa 方式是什么?

4

1 回答 1

5

最明显的方法是 apply -takeUntil:,它在提供的信号发送值或完成时完成信号。由于您只希望在完成时incomingWorkSubject完成,而不是在它发送值时完成,所以使用-ignoreValues.

为了便于阅读,我已将计时器信号提取到变量中。

RACSignal *timer = [[RACSignal
    interval:0.5 onScheduler:[RACScheduler scheduler]]
    filter:^BOOL(__unused id _x) {
        return isThereAProblemInDeliveringWork();
    }];

RACSignal *signal = [[RACSignal
    merge:@[ incomingWorkSubject, timer ]]
    takeUntil:[incomingWorkSubject ignoreValues]];

为了讨论起见,还有另一种可能符合要求的解决方法。相反,使用上面定义的,使用using的timer样本。如何做到这一点取决于. 如果它是,并且您知道有一个值可用,则可以直接对其进行采样。incomingWorkSubject-sample:incomingWorkSubjectRACReplaySubject

RACSignal *signal = [RACSignal merge:@[
    incomingWorkSubject,
    [incomingWorkSubject sample:timer]
]];

但是,如果incomingWorkSubject是 vanilla RACSubject,那么您需要编写一个新信号以包含一个初始值 with -startWith:,以便在触发-sample:时发送一个值。timer

RACSignal *signal = [RACSignal merge:@[
    incomingWorkSubject,
    [[incomingWorkSubject startWith:initialValue] sample:timer]
]];

用英语来说,这会创建一个从 发送最新值的信号incomingWorkSubject,并且还会从 发送一个最近缓存的值incomingWorkSubject,但前提是定期检查 toisThereAProblemInDeliveringWork()是肯定的。合并信号在完成时incomingWorkSubject完成。

于 2013-09-18T22:09:51.340 回答