ReactiveCocoa,在启用按钮时组合两个信号

时间:2015-05-18 08:10:21

标签: ios objective-c mvvm reactive-cocoa

我使用的是MVVM架构,我有两个信号:

RACSignal *internetEnabledSignal = RACObserve(self.regWizardVehicleViewModel, internetConnectionEnabled);
RACSignal *executingRegistrationSignal = RACObserve(self.regWizardVehicleViewModel, isExecuting);

我需要在启用按钮的属性上组合和绑定信号。如果没有任何连接或某些方法正在执行时,需要禁用Button。我正在寻找解决方案,但我不知道如何将信号与OR结合起来。有没有办法做到这一点?下一个问题是:我正在使用MBProgressHUD。我想在我的模型中执行我的异步方法时显示HUD。 MBProgressHUD有显示和隐藏方法,不能将它绑定到启用按钮的属性吗?

2 个答案:

答案 0 :(得分:9)

有一种方便的方法,-and可以使用" boolean"价值信号更容易:

  

返回一个信号,该信号对元组中的每个NSNumber应用AND。

要获得NSNumbers的元组,请使用combineLatestWith:,如下所示:

   RAC(self.button, enabled) =[[[executingRegistrationSignal not] 
        combineLatestWith:internetEnabledSignal]
         and];

答案 1 :(得分:5)

如果我没有误解你,那么使用combineLatest:reduce:可以很容易地实现功能,如下所示:

RACSignal * enabledSignal = 
[RACSignal combineLatest:@[internetEnabledSignal, executingRegistrationSignal] 
reduce:^id(NSNumber * internetEnabled, NSNumber * isExecuting) {
    return @(internetEnabled.boolValue && !isExecuting.boolValue);
}].distinctUntilChanged;

RAC(self.button, enabled) = enabledSignal;

combineLatest:reduce:在所有信号至少被触发一次之前不会发送任何下一个事件,所以请记住这一点。

编辑:请通过便捷方法查看Michał对更酷解决方案的回答。

至于你的另一个问题,我对MBProgressHUD不是很熟悉,但这应该可以解决问题:

[self.hud rac_liftSelector:@selector(show:) withSignalsFromArray:@[
    [enabledSignal ignore:@NO]
]];
[self.hud rac_liftSelector:@selector(hide:) withSignalsFromArray:@[
    [[enabledSignal ignore:@YES] mapReplace:@YES]
]];

这有点作弊,我们正在利用RAC对这些信号的热切期望来解决副作用,但如果你是一个实用主义者而不是像我这样迂腐的理想主义者,你可能不介意。

这段代码发生的事情是我们要求RAC在我们提供的数组中的每个信号触发后执行给定的选择器,因此它很像combineLatest:。我们正在使用mapReplace:,因为它会将该信号用作(BOOL)animated参数(这是欺骗的另一个原因)。