Search code examples
objective-creactive-programmingreactive-cocoa

Is it possible to define a placeholder signal for a signal that hasn't yet been defined in ReactiveCocoa?


As an example, say I have a JSViewController with a UIButton. I'd like to expose a signal representing [UIButton rac_signalForControlEvents:UIControlEventsTouchUpInside] in the interface for JSViewController, but I'll be loading the UIButton in -viewDidLoad:.

This presents a problem: the UIButton's signal isn't available until the -viewDidLoad is executed.

@interface JSViewController : UIViewController
@property (nonatomic, strong) RACSignal *buttonPressedSignal;
@end

@implementation JSViewController

- (instancetype)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil {
    // buttonPressedSignal needs to be defined here
}

- (void)viewDidLoad {
    UIButton *button = [UIButton buttonWithType:UIButtonTypeSystem];
    [self.view addSubview:button];
    self.buttonPressedSignal = [button rac_signalForControlEvents:UIControlEventTouchUpInside];
}

@end

Is there a way I can create a "placeholder" signal that forwards events from [button rac_signalForControlEvents:UIControlEventTouchUpInside] ?


Solution

  • Observe the view controller's isViewLoaded property, filter out NO values, and then -flattenMap: the YES value into a signal of the button's control events:

    - (RACSignal *)buttonEvents
    {
        @weakify(self);
        return [[[RACObserve(self, isViewLoaded)
                filter:^BOOL(NSNumber *isLoaded) {
    
                    return isLoaded.boolValue;
    
                }]
                take:1]
                flattenMap:^id(id _) {
    
                    @strongify(self);
                    return [self.myButton rac_signalForControlEvents:UIControlEventTouchUpInside];
    
                }];
    }