Search code examples
iphoneioscocoa-touchreactive-cocoa

Reactive Cocoa reduce block never gets called


I'm trying to wrap head around Reactive Cocoa, everything works fine except RAC(self.windButton.enabled) sections (at the bottom), reduce blocks never gets called. Would be glad if someone could point me my errors. The code is self-explaining, basically app looks like this:

App screenshot

Here is implementation

#import "ViewController.h"

@interface ViewController ()

@property (strong, nonatomic) NSNumber *winding;
@property (strong, nonatomic) NSNumber *minWinding;
@property (strong, nonatomic) NSNumber *maxWinding;

@property (weak, nonatomic) IBOutlet UIButton *windButton;
@property (weak, nonatomic) IBOutlet UIButton *unwindButton;
@property (weak, nonatomic) IBOutlet UILabel *windingLabel;

@end

@implementation ViewController

- (void)viewDidLoad
{
    [super viewDidLoad];

    self.winding = @0;
    self.minWinding = @0;
    self.maxWinding = @15;

    RACSignal *windingSignal = RACAble(self.winding);
    RACSignal *maxWindingSignal = RACAble(self.maxWinding);
    RACSignal *minWindingSignal = RACAble(self.minWinding);

    RAC(self.windingLabel.text) = [windingSignal map:^id(NSNumber *winding) {
        return winding.stringValue;
    }];

    [[self.windButton rac_signalForControlEvents:UIControlEventTouchUpInside]
     subscribeNext:^(id sender) {
        self.winding = @(self.winding.integerValue + 1);
    }];

    [[self.unwindButton rac_signalForControlEvents:UIControlEventTouchUpInside]
     subscribeNext:^(id sender) {
        self.winding = @(self.winding.integerValue - 1);
    }];

    RAC(self.windButton.enabled) = [RACSignal
                              combineLatest:@[windingSignal, maxWindingSignal]
                              reduce:^(NSNumber *winding, NSNumber *maxWinding) {
                                  return @(winding.intValue < maxWinding.intValue);
                              }];


    RAC(self.unwindButton.enabled) = [RACSignal
                               combineLatest:@[windingSignal, minWindingSignal]
                               reduce:^(NSNumber *winding, NSNumber *minWinding) {
                                   return @(winding.intValue > minWinding.intValue);
                               }];
}

My problem is that buttons never get disabled.


Solution

  • I had to use RACAbleWithStart to pre-fill signal with initial values since combineLatest method waits until every provided signal has some value.

    RACSignal *windingSignal = RACAbleWithStart(self.winding);
    RACSignal *maxWindingSignal = RACAbleWithStart(self.maxWinding);
    RACSignal *minWindingSignal = RACAbleWithStart(self.minWinding);