RACSignal combineLatest使用多个UIControl

jrt*_*ton 3 ios reactive-cocoa

我正在尝试使用Reactive Cocoa,我在组合来自多个UIControl的信号时遇到了麻烦.

我正在为UIEdgeInsets创建一个编辑器,并有四个UISteppers,用于顶部,左侧,底部和右侧插入.

我想要做的是:

RAC(self.insets) = [RACSignal combineLatest:@[
          [topStepper rac_signalForControlEvents:UIControlEventValueChanged],
          [leftStepper rac_signalForControlEvents:UIControlEventValueChanged],
          [bottomStepper rac_signalForControlEvents:UIControlEventValueChanged],
          [rightStepper rac_signalForControlEvents:UIControlEventValueChanged]
          ] reduce:^(UIStepper *top, UIStepper *left, UIStepper *bottom, UIStepper *right) {
              return [NSValue valueWithUIEdgeInsets:UIEdgeInsetsMake(top.value, left.value, bottom.value, right.value)];
          }];
Run Code Online (Sandbox Code Playgroud)

但是,这绝不会导致信号被处理.

如果我只包含一个信号,如下所示:

RAC(self.insets) = [RACSignal combineLatest:@[
    [topStepper rac_signalForControlEvents:UIControlEventValueChanged]]
    reduce:^(UIStepper *top) {
        return [NSValue valueWithUIEdgeInsets:UIEdgeInsetsMake(top.value, 0.0,0.0,0.0)];
    }];
Run Code Online (Sandbox Code Playgroud)

它按预期工作(观察任何其他步进器单独工作正常)但对于多个控件,我什么也得不到.我可以通过观察每个控件作为单独的信号来解决,但这似乎忽略了combineLatest方法的要点.我做错了什么,或者我应该在RAC项目上提出问题?

Cod*_*aFi 6

这是因为为了combineLatest:reduce:运行,该阵列中的每个控件必须至少广播一个信号才能开始(观察最新信号的任何非突变值都不会调用reduce块).您可以非常清楚地看到它,因为每个控件必须至少被点击一次以开始生成有效信号,这些信号会像您期望的那样被抛出并处理.正如Justin所说,你可以使信号具有一个初始值,它应该比调用更快地获得正确的值并运行得更快-sendActionForControlEvent:

RAC(self.insets) = [RACSignal combineLatest:@[
                    [[self.topStepper rac_signalForControlEvents:UIControlEventValueChanged]startWith:nil],
                    [[self.leftStepper rac_signalForControlEvents:UIControlEventValueChanged]startWith:nil],
                    [[self.bottomStepper rac_signalForControlEvents:UIControlEventValueChanged]startWith:nil],
                    [[self.rightStepper rac_signalForControlEvents:UIControlEventValueChanged]startWith:nil]
                    ] reduce:^(UIStepper *top, UIStepper *left, UIStepper *bottom, UIStepper *right) {
                        return [NSValue valueWithUIEdgeInsets:UIEdgeInsetsMake(top.value, left.value, bottom.value, right.value)];
                    }];
Run Code Online (Sandbox Code Playgroud)