RACSignal用于NSArray对象

时间:2013-10-30 20:44:37

标签: objective-c reactive-cocoa

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

@property(非原子,强)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数等于viewModels的总数,则此信号将告诉命令被启用。

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

RACSequence *selectedViewModels = [[self.viewModels.rac_sequence

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

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

如何创建有效信号?

1 个答案:

答案 0 :(得分:6)

要观察所有最新的视图模型(以及最新的视图模型),我们需要在每次数组更改时设置新的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];