Search code examples
objective-creactive-cocoa

Using combineLatest, is there a way to find out which signal emitted the event?


As the title states is there a way to perform the following:

[[RACSignal combineLatest:@[signal1, signal2]] subscribNext:^id(RACTuple *signals) {
    // Did signal1 or signal2 emit an event?
}];

So in the subscribeNext block I currently don't know which signal fired.

The problem I've trying to solve is one that involves generating signals for selectors (using rac_signalForSelector) and I wantt to be notified when any one of those methods is fired. I want to merge the events together but I don't want the latest value for any of them except for the method that was actually called.

e.g.

RACSignal *signal1 = [self rac_signalForSelector@selector(method1:)];
RACSignal *signal2 = [self rac_signalForSelector@selector(method2:)];

[[RACSignal combineLatest:@[signal1, signal2]] subscribNext:^id(RACTuple *signals) {
    // Did signal1 or signal2 emit an event?
}];

Solution

  • Assuming that signal1 and signal2 in your example are sending the same type of values, and you want to do the same thing with the values from each signal, you can use merge: instead of combineLatest: to just get a signal of the values that each fires:

    [[RACSignal merge:@[signal1, signal2]] subscribeNext:^(NSObject *latestValue) {
        NSLog(@"%@", latestValue);
    }];
    

    If you want to treat them differently, then there's no need to use combineLatest: or merge: at all -- you can just subscribe to each one independently.

    Note that one difference between merge: and combineLatest: is that, with merge:, your block will be invoked as soon as the first method is invoked -- it won't wait until every method is invoked at least once before it starts firing, as combineLatest: would. If that behavior is desirable, it can be achieved with the then: operator.


    In the case that you do need to know not only the argument to the "most recently invoked" method but also the arguments from the last time the other methods were invoked, and you do need to wait until every method has been invoked at least once... one thing you could do is map each signal into a tuple of (id whateverTheyActuallySent, NSUInteger sharedMonotonicallyIncreasingIdentifier), then combine those signals, then sort them based on that identifier.

    It would be... inelegant, but only a very odd situation would warrant that, and if you do believe that's the best approach it might be good to zoom out one more level to see if something else could be changed so that you didn't have to do that after all.