是否可以为ReactiveCocoa中尚未定义的信号定义占位符信号?

时间:2014-03-14 20:27:31

标签: objective-c reactive-programming reactive-cocoa

例如,假设我JSViewController有一个UIButton。我想在[UIButton rac_signalForControlEvents:UIControlEventsTouchUpInside]的界面中公开代表JSViewController的信号,但我会在UIButton中加载-viewDidLoad:

这会出现问题:UIButton的信号在执行-viewDidLoad之前无法使用。

@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

有没有办法可以创建一个"占位符"发出来自[button rac_signalForControlEvents:UIControlEventTouchUpInside]的事件的信号?

2 个答案:

答案 0 :(得分:3)

一种解决方案是创建RACSubject作为占位符信号,并在信号创建后订阅UIButton信号:

@interface JSViewController : UIViewController
@property (nonatomic, strong) RACSubject *buttonPressedSubject;
@end

@implementation JSViewController

- (instancetype)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil {
    self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
    if (self) {
        _buttonPressedSubject = [RACSubject subject];
    }

    return self;
}

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

@end

答案 1 :(得分:1)

观察视图控制器的isViewLoaded属性,过滤掉NO值,然后将-flattenMap: YES值转换为按钮控件事件的信号:

- (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];

            }];
}