这是一种方法:假设您有一个 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 操作(对值流进行操作)替换正常操作(对值进行操作)。
每个操作代表一个将值流转换为另一个值流的步骤。每一步都会产生一个新信号,它代表将我们的初始值流转换为我们想要的值流的进一步步骤。
相关的,最后一个操作没有输出信号,只是我们产生副作用的地方。将转换和组合值的逻辑与执行副作用的逻辑分开是一种很好的做法。这样,我们可以向锁定信号添加额外的观察者,或者重构影响锁定的代码,而不用担心意外后果。
下一个很好的练习是处理对正确组合或锁上轮子数量的更改。