我尝试了以下但没有成功。使用-subscribeNext:
的等价物按预期工作。
// A
[[_viewModel.loginCommand.executionSignals flatten] subscribeCompleted:^{
NSLog(@"A");
}];
我唯一的工作实现如下:
// B
[_viewModel.loginCommand.executionSignals subscribeNext:^(RACSignal *loginSignal) {
[loginSignal subscribeCompleted:^{
NSLog(@"B");
}];
}];
为什么没有-flatten
在" A"中工作,以及如何重写" B"不使用嵌套订阅?
答案 0 :(得分:10)
-flatten
运算符返回仅在所有内部信号都已完成时才完成的信号,这也需要外部信号完成。 -concat
也是如此。因此,一旦您应用任何一个运算符,结果信号就不会表示单个完成,只有最终的汇总完成。
替代嵌套订阅,您可以转换内部信号,以便它们发送表示完成的值。一种方法是使用-materialize
:
[[[_viewModel.loginCommand.executionSignals
map:^(RACSignal *loginSignal) {
// Using -ignoreValues ensures only the completion event is sent.
return [[loginSignal ignoreValues] materialize];
}]
concat]
subscribeNext:^(RACEvent *event) {
NSLog(@"Completed: %@", event);
}];
请注意,我使用了-concat
而不是-flatten
,因为它与RACCommand
的默认串行执行的语义相匹配。在这种情况下,它们最终会做同样的事情,-flatten
退化为-concat
的行为,因为该命令一次只能执行一个信号。
使用-materialize
并不是实现此目的的唯一方法,它恰好发送一个表示完成的值,但这可能是您认为对您的用例有重大意义的任何值。
答案 1 :(得分:0)
我只是认为,从技术上讲,成功完成只是将执行状态更改为NO,在-executionSingals
至少发送一次值后,执行状态在上次更改为YES后没有错误。 / p>
基于这样的想法,我做了一个类别:
#import "RACCommand+ARLCompletedSignal.h"
@implementation RACCommand (ARLCompletedSignal)
- (RACSignal *)completed
{
RACSignal *executing = self.executing;
RACSignal *signals = self.executionSignals;
RACSignal *errors = self.errors;
RACSignal *startingExecution = [RACSignal combineLatest:@[executing, [signals take:1]]
reduce:^id(NSNumber *executing, id _){ return executing; }];
return [[startingExecution
ignore:@NO]
flattenMap:^RACStream *(id value) {
RACSignal *comletedOrFailed = [[executing ignore:@YES] subscribeOn:[RACScheduler scheduler]];
return [[[comletedOrFailed take:1] takeUntil:errors] map:^id(id value) { return nil; }];
}];
}
@end
标题:
@interface RACCommand (ARLCompletedSignal)
@property (nonatomic, readonly) RACSignal *completed;
@end
当命令成功完成其操作时,-comleted
发送nil。
同样在https://gist.github.com/slabko/546de430a16994a5da8e你可以找到版本,如果操作成功完成则发送YES,否则发送NO。
我在一些非常简单的案例中尝试过它并且有效。请告诉我,如果它不适合你的话。
然而,我相信,在大多数情况下,在将原始信号传递给命令之前,订阅原始信号的完成是最好的,“无懈可击”的选项。