Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

RACSignal: how to reduce on arbitrarily large combine

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.

like image 261
Clay Bridges Avatar asked Mar 24 '23 04:03

Clay Bridges


1 Answers

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.

like image 181
yonosoytu Avatar answered Apr 01 '23 01:04

yonosoytu