3

我对 Reactive Cocoa 完全陌生。在花了一些时间阅读文档和一些教程之后,我想我在尝试做一些相对简单的事情时一定错过了一个技巧(我希望!)。

我正在尝试编写 4 位密码锁的逻辑作为练习。

用户使用滚轮输入,当数字 1 正确时只能输入数字 2,选择数字 2 时只能输入数字 3 等等。基本上,我需要观看输入的数字流,检查“正确”数字,并且,当它们相等时,推进系统检查通行证组合的第二个数字。

我可以看到如何从用户输入中生成 RACSignal,但我不确定使用什么模式来检查“正确”数字以便使用...filter:?...combineLatest 推进序列 RACSequence: ?

我只是想弄清楚这一点,所以代码示例很受赞赏,但是正确方向的一般概念指针会很棒。

4

1 回答 1

1

这是一种方法:假设您有一个 NSNumbers 信号,表示锁上每个轮子的当前值,并successIndicator指示组合是否正确:

NSArray *correctCombination = @[@1, @2, @3, @4)];
RACSignal *currentCombination = [RACSignal combineLatest:@[digit1, digit2, digit3, digit4];

RACSignal *(^hasCorrectValue)(NSUInteger idx) ^(NSUInteger idx){
    return [currentCombination map:^(RACTuple *currentCombination) {
        return [currentCombination[idx] isEqual:correctCombination[idx]];
    }];
};

__block RACSignal *(^hasUnlockedStage)(NSUInteger idx) = ^(NSUInteger idx){
    if (idx == 0) return hasCorrectValue(idx);
    else return [hasCorrectValue(idx) and:hasUnlockedStage(idx - 1)];
};

[hasUnlockedStage(0) setKeypath:@keypath(wheel2, enabled) onObject:wheel2];
[hasUnlockedStage(1) setKeypath:@keypath(wheel3, enabled) onObject:wheel3];
[hasUnlockedStage(2) setKeypath:@keypath(wheel4, enabled) onObject:wheel4];
[hasUnlockedStage(3) setKeypath:@keypath(successIndicator, active) onObject:successIndicator];

hasUnlockedStage = nil; // nil out recursive block

逻辑发生的中间部分与非反应性非常相似:

BOOL(^hasCorrectValue)(NSUInteger idx) ^(NSUInteger idx){
   return [[views[idx] currentValue] isEqual:[correctCombination[idx] currentValue]];
};

__block BOOL(^hasUnlockedStage)(NSUInteger idx) = ^(NSUInteger idx){
    if (idx == 0) return hasCorrectValue(idx);
    else return hasCorrectValue(idx) && hasUnlockedStage(idx - 1);
};

一旦所有输入都表示为信号,我们就可以像在标准 Objective-C 中那样大致进行,用 RAC 操作(对值流进行操作)替换正常操作(对值进行操作)。

每个操作代表一个将值流转换为另一个值流的步骤。每一步都会产生一个新信号,它代表将我们的初始值流转换为我们想要的值流的进一步步骤。

相关的,最后一个操作没有输出信号,只是我们产生副作用的地方。将转换和组合值的逻辑与执行副作用的逻辑分开是一种很好的做法。这样,我们可以向锁定信号添加额外的观察者,或者重构影响锁定的代码,而不用担心意外后果。

下一个很好的练习是处理对正确组合或锁上轮子数量的更改。

于 2013-09-21T21:51:33.977 回答