I have two RACSignal
s one of which is a timer and the other one indicates there's work to do. Since the work indication is sometimes unreliable, there's the timer, which takes care that work will be done periodically if the precise notifications don't work.
The general setup is:
RACSignal *signal = [RACSignal merge:@[
[[RACSignal interval:0.5 onScheduler:[RACScheduler scheduler]]
filter:^BOOL(__unused id _x) {
return isThereAProblemInDeliveringWork();
}],
incomingWorkSubject
]];
Now I want signal
to complete as soon as incomingWorkSubject
was completed. So, in general: Complete the merged signal as soon as any of its input signals completed. Unfortunately, [RACSignal merge:...]
doesn't do what I want and apparently waits for all incoming signals to complete.
What would be the ReactiveCocoa-way of achieving that?
The most obvious approach is to apply -takeUntil:
, which completes a signal when a supplied signal either sends a value, or completes. Since you only want completion when incomingWorkSubject
completes, and not when it sends a value, use -ignoreValues
.
I've extracted the timer signal to a variable for readability.
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]];
For the sake of discussion, there's another way of going about this that might fit the bill. Instead, using the timer
defined above, take samples of incomingWorkSubject
using -sample:
. How you do this depends on the nature of incomingWorkSubject
. If it's a RACReplaySubject
, and you know a value will be available, it can be sampled directly.
RACSignal *signal = [RACSignal merge:@[
incomingWorkSubject,
[incomingWorkSubject sample:timer]
]];
However, if incomingWorkSubject
is a vanilla RACSubject
, then you'll need to compose a new signal to include an initial value, with -startWith:
, so that -sample:
has a value to send when timer
fires.
RACSignal *signal = [RACSignal merge:@[
incomingWorkSubject,
[[incomingWorkSubject startWith:initialValue] sample:timer]
]];
In english, this creates a signal that sends the latest value from incomingWorkSubject
, and also will send a recent cached value from incomingWorkSubject
, but only when a periodic check to isThereAProblemInDeliveringWork()
is affirmative. The merged signal completes when incomingWorkSubject
completes.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With