RACSignal: how to reduce on arbitrarily large combine

objective-c, reactive-cocoa, reactive-programming

Solution

You can use map:

RAC(self.enabled) = [[RACSignal combineLatest:arrayOfSignals]
                     map:^(RACTuple *signalValues) {
                       // something
                     }
                    ];

A `RACTuple` can be manipulated in many ways, it conforms `NSFastEnumeration`, it has the `allObjects` method and also the `rac_sequence` method. You can for example combine all boolean values this way:

RAC(self.enabled) = [[RACSignal combineLatest:arrayOfSignals]
                     map:^(RACTuple *signalValues) {
                       return @([signalValues.rac_sequence all:^BOOL(NSNumber *value) {
                         return [value boolValue];
                       }]);
                     }
                    ];

Hope it helps.

Problem

Consider an example (paraphrased) from the ReactiveCocoa Introduction, which enables based on whether the `.password` and `.passwordConfirm` text fields match: ``` RAC(self.enabled) = [RACSignal combineLatest:@[ RACAble(self.password), RACAble(self.passwordConfirm) ] reduce:^(NSString *password, NSString *passwordConfirm) { return @([passwordConfirm isEqualToString:password]); }]; ``` Here we know at compile time how many and what things we are combining, and it is useful to destructure/map the "combine" array into multiple arguments to the reduce block. What about when that won't work. For instance, if you want: ``` RAC(self.enabled) = [RACSignal combineLatest:arrayOfSignals reduceAll:^(NSArray *signalValues) { // made this up! don't try at home. // something ... }]; ``` How do you do this with ReactiveCocoa? UPDATE: the accepted answer's comments help explain what I was missing.

Original source