为什么RACCommand的块返回信号?

时间:2013-10-18 02:37:29

标签: ios objective-c reactive-programming reactive-cocoa

我一直在学习很多ReactiveCocoa但有一件事让我感到困惑:为什么RACCommand上的信号块本身会返回一个信号?

我理解RACCommand的用例,它的canExecute信号和信号块,以及如何将它连接到UI元素。但是,返回[RACSignal empty]以外的东西会有什么情况呢?

infoButton.rac_command = [[RACCommand alloc] initWithSignalBlock:^RACSignal *(id input) {
    // Do stuff

    return [RACSignal empty];
}];

4 个答案:

答案 0 :(得分:28)

每条规则都有例外,但通常您希望返回的信号捕获所有“// Do stuff”。换句话说,你的例子会更好:

infoButton.rac_command = [[RACCommand alloc] initWithSignalBlock:^(id input) {
    return [RACSignal defer:^{
        // Do stuff

        return [RACSignal empty];
    }];
}];

此更改的直接好处是,在“// Do stuff”期间,您的infoButton将被禁用,以防止点击/点击它,直到返回的信号完成为止。在您的原始代码中,“do stuff”在信号之外,因此您的按钮不会被正确禁用。

对于没有太多延迟的工作,例如根据按钮点击进行UI更改,RACCommand的启用/禁用功能对您不会有太大帮助。但是,如果工作是网络请求,或者其他一些可能长时间运行的工作(例如媒体处理),那么您肯定希望在信号中捕获所有这些工作。

答案 1 :(得分:7)

想象一下,您有一个应该从网络加载项目列表的命令。您可以在信号块中使用副作用或返回实际发送这些项目的信号。在后一种情况下,您可以执行以下操作:

RAC(self, items) = [loadItems.executionSignals switchToLatest];

此外,信号发送的所有错误都将重定向到errors信号,因此:

[self rac_liftSelector:@selector(displayError:) 
           withSignals:loadItems.errors, nil];

使用[RACSignal empty]驱动的命令是不可能的。

答案 2 :(得分:6)

我有一个可能有用的例子,尽管其他人可能能够更好地解释它。 RACCommand Example

但基本上,你返回+empty的方式似乎有点无意义,因为调用命令基本上会使用我们想要避免的副作用。

答案 3 :(得分:2)

而不是使用它:

infoButton.rac_command = [[RACCommand alloc] initWithSignalBlock:^(id input) {
    return [RACSignal defer:^{
        // Do stuff

        return nil;
    }];
}];

您可以使用此内置方法来控制按钮状态:

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