4

我的 ViewController 上有一个 NSArray 的 ViewModel 对象:

@property (nonatomic, strong) NSArray *viewModels;

ViewModel 对象看起来像这样:

@interface ViewModel : NSObject

@property (nonatomic) BOOL isSelected;

@end

我正在尝试在 RACCommand 的 init 方法上为 enabledSignal 创建一个 RACSignal:

- (id)initWithEnabled:(RACSignal *)enabledSignal signalBlock:(RACSignal * (^)(id input))signalBlock

如果选择了 0 个 viewModel 对象,或者选择的 viewModel 的数量等于 viewModel 的总数,此信号将告诉命令启用。

我可以创建一个 RACSequence,它将为我提供此代码选择的 viewModel 对象:

RACSequence *selectedViewModels = [[self.viewModels.rac_sequence

                                        filter:^BOOL(ViewModel *viewModel) {
                                            return viewModel.isSelected == YES;
                                        }]

                                       map:^id(ViewModel *viewModel) {
                                           return viewModel;
                                       }];

我将如何创建有效信号?

4

1 回答 1

7

为了观察所有最新的视图模型(并且只有最新的视图模型)的变化,我们需要在每次数组变化时设置新的 KVO 观察。

最自然的表示方式是使用信号信号。每个“内部”信号代表对一个版本的一组观察viewModels,然后我们将使用它-switchToLatest来确保只有最新的信号生效:

@weakify(self);

RACSignal *enabled = [[RACObserve(self, viewModels)
    // Map _each_ array of view models to a signal determining whether the command
    // should be enabled.
    map:^(NSArray *viewModels) {
        RACSequence *selectionSignals = [[viewModels.rac_sequence
            map:^(ViewModel *viewModel) {
                // RACObserve() implicitly retains `self`, so we need to avoid
                // a retain cycle.
                @strongify(self);

                // Observe each view model's `isSelected` property for changes.
                return RACObserve(viewModel, isSelected);
            }]
            // Ensure we always have one YES for the -and below.
            startWith:[RACSignal return:@YES]];

        // Sends YES whenever all of the view models are selected, NO otherwise.
        return [[RACSignal
            combineLatest:selectionSignals]
            and];
    }]
    // Then, ensure that we only subscribe to the _latest_ signal returned from
    // the block above (i.e., the observations from the latest `viewModels`).
    switchToLatest];
于 2013-10-31T15:46:42.570 回答