8

也许我仍然在反应式学习曲线上苦苦挣扎,但我很难弄清楚如何将非反应式类与我的反应式代码的其余部分联系起来。我正在使用一个类别来扩展非反应性类。

该属性只是一个 Enum,表示网络操作的当前状态,例如 New、Submitted、Processing 和 Completed。现在我已经在我的类别中编写了以下方法:

@implementation JRequestBase (RACExtensions)
- (RACSignal*) rac_RequestStateSignal
{
    return  RACAble(self, state);
}
@end

但是,当状态从 Processing -> Completed 或从任何状态转换为 Errored 时,我希望此信号发送 Completed 或 Error 而不是 Next Value。我怎样才能在一个类别中做到这一点?我想做类似的事情:

@implementation JRequestBase (RACExtensions)
- (RACSignal*) rac_RequestStateSignal
{
    return  [RACAble(self, state) map:^(NSNumber *state){
                 if ([state intValue] == iRequestStateComplete)
                 {    
                     # SEND COMPLETE
                 }
                 else if ([state intValue] == iRequestStateErrored)
                 { 
                     # SEND ERROR
                 }
                 else
                 { 
                     return state;
                 }
            }];
}
@end

编辑:我查看了 GHAPIDemo 并提出了以下内容:

- (RACSignal*) rac_RequestSignal
{
    RACSubject *subject = [[RACReplaySubject alloc] init];
    [[RACAble(self, state) subscribeNext:^(NSNumber* s){
        if ( [s intValue] == JRequestStateCompleted)
        {
            [subject sendNext:self];
            [subject sendCompleted];
        }
        else if ([s intValue] == JRequestStateErrored)
        {
            NSMutableDictionary *dict = [NSMutableDictionary dictionary];
            // .. Set up dict with necessary values.
            NSError *error = [NSError errorWithDomain:@"blah" code:1 userInfo:dict];

            [subject sendError:error];
        }
    }];
    return subject;
}

我不是 100% 确定这是正确的方法,但它似乎正在工作。

4

1 回答 1

11

每当您想映射值→信号事件,而不是值→值时,您应该使用-flattenMap:返回对应于每个输入值的信号。然后,正如名称中的“扁平化”所暗示的那样,它们将组合成一个结果信号。

但是,这种情况有点不同,因为您希望在获得Complete值后立即终止信号。我们将用它-takeUntilBlock:来表示那部分。

生成的代码如下所示:

- (RACSignal*) rac_RequestStateSignal
{
    return [[RACObserve(self, state)
        takeUntilBlock:^ BOOL (NSNumber *state){
            return [state intValue] == iRequestStateComplete;
        }]
        flattenMap:^(NSNumber *state){
            if ([state intValue] == iRequestStateErrored)
            { 
                // Create a meaningful NSError here if you can.
                return [RACSignal error:nil];
            }
            else
            { 
                return [RACSignal return:state];
            }
        }];
}

(我使用RACObserve是因为ReactiveCocoa 2.0现在是唯一受支持的版本,但你可以使用RACAble直到你准备好升级。)

作为一般规则,您应该尽可能避免使用主题,因为它们会使代码更有状态并减少惰性。

于 2013-09-13T17:53:44.297 回答