【问题标题】:RACSignal combineLatest using multiple UIControlsRACSignal combineLatest 使用多个 UIControls
【发布时间】:2013-03-08 16:07:26
【问题描述】:

我正在尝试使用 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)];
          }];

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

如果我只包含一个信号,像这样:

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

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

【问题讨论】:

    标签: ios reactive-cocoa


    【解决方案1】:

    这是因为为了让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)];
                        }];
    

    【讨论】:

    • 有道理,但它很脏。
    • 你可以使用-startWith:给信号一个初始值。此外,nil 值不会取消+combineLatest:。它们会像任何其他值一样被传递到 reduce 块中。
    • @JustinSpahr-Summers 当我用他的代码运行测试时,reduce 块和 setter 都没有被调用,直到所有四个步进器的值都发生了变异。也许取消不是正确的选择。
    • 正确,+combineLatest: 不会被调用,直到所有信号都发送了至少一个值。但是nil是一个完全有效的信号发送值,发送nil的所有四个步进器都会成功触发块。
    • @JustinSpahr-Summers Better?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2012-09-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-06-25
    相关资源
    最近更新 更多