合并两个RACSignals,在首次完成时完成

时间:2013-09-18 15:17:01

标签: objective-c reactive-programming reactive-cocoa

我有两个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实现这一目标的方式是什么?

1 个答案:

答案 0 :(得分:5)

最明显的方法是应用-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]];

为了讨论起见,还有另一种方法可以满足这个要求。相反,使用上面定义的timer,使用-sample:获取incomingWorkSubject的样本。如何执行此操作取决于incomingWorkSubject的性质。如果它是RACReplaySubject,并且您知道某个值可用,则可以直接对其进行采样。

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

但是,如果incomingWorkSubject是一个香草RACSubject,那么您需要撰写一个新信号,以包含-startWith:的初始值,以便-sample:timer点火时发送的值。

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

在英语中,这会创建一个信号,该信号从incomingWorkSubject发送最新值,并且还会从incomingWorkSubject发送最近的缓存值,但仅在定期检查isThereAProblemInDeliveringWork()时才会发送肯定。 incomingWorkSubject完成后合并的信号完成。