我有两个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实现这一目标的方式是什么?
答案 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
完成后合并的信号完成。