我对Reactive Cocoa完全不熟悉。在花了一些时间浏览文档和一些教程之后,我想我一定是在尝试做一些相对简单的事情时错过了一个技巧(我希望!)。
我正在尝试将4位数组合锁的逻辑编写为练习。
用户使用滚轮输入,只能在数字1正确时输入数字2,在选择数字2时输入数字3等等。基本上,我需要观察输入的数字流,检查“正确”数字和,当它们相等时,使系统前进以检查通过组合的第二个数字。
我可以看到如何从用户输入中创建RACSignal,但是我不确定使用什么模式来检查'正确'数字以便使用...过滤序列RACSequence:?.. .combineLatest:?
我只是试图理解这一点,所以感谢代码示例,但正确方向的一般概念指针会很棒。
答案 0 :(得分: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操作(对值流进行操作)替换为正常操作(对值进行操作)。
每个操作代表一个步骤,将值流转换为另一个值流。每个步骤都会产生一个新信号,表示将我们的初始值流转换为我们想要的值流的进一步步骤。
相关地,最后一个操作没有输出信号,只是我们引起任何副作用的地方。将转换和组合值的逻辑与执行副作用的逻辑分开是一种很好的做法。这样,我们可以为锁定信号添加额外的观察者,或者重构影响锁定的代码,而不必担心意外后果。
一个不错的下一个练习是处理对正确组合的更改,或锁上轮子的数量。