5

我有通过 NSNotificationCenter 的成功通知和失败通知。我编写了一些测试来弄清楚如何将来自这两个通知的信号组合成一个信号,该信号在失败通知命中时提供错误,在成功通知命中时提供下一个信号。

目前完整的块不会被击中,下一个和错误会被击中。

另外,第二个额外的问题:为什么 @[errorNotification, completeNotification].rac_sequence.signal 不做与下面的信号创建信号相同的事情?

代码:

-(void)test_flatten_signal_of_signals_and_convert_notification_to_error{
    RACSignal *errorNotification = [[[NSNotificationCenter defaultCenter] rac_addObserverForName:@"TEST_FAILURE" object:nil] take:1];


    errorNotification = [errorNotification flattenMap:^(NSNotification *notification){
        return [RACSignal error:[NSError errorWithDomain:@"RAC_TEST" code:1 userInfo:nil]];
    }];

    RACSubject *completeNotification = [RACSubject subject];

    RACSignal *signalOfSignals = [[RACSignal
                                   createSignal:^RACDisposable *(id<RACSubscriber> subscriber){
                                       [subscriber sendNext:errorNotification];
                                       [subscriber sendNext:completeNotification];
                                       [subscriber sendCompleted];
                                       return nil;
                                   }]
                                  flatten];


    __block BOOL hitCompleted = NO;

    [signalOfSignals
     subscribeNext:^(id val){
         STFail(nil);
     }
     error:^(NSError *err){
         hitCompleted = YES;
     }
     completed:^{
         STFail(nil);
     }];

    [[NSNotificationCenter defaultCenter] postNotificationName:@"TEST" object:self];

    STAssertTrue(hitCompleted, nil);
}

-(void)test_flatten_signal_of_signals_and_hits_next_complete_on_notification{
    RACSubject *errorNotification = [RACSubject subject];

    RACSignal *completeNotification = [[[NSNotificationCenter defaultCenter] rac_addObserverForName:@"TEST_SUCESS" object:nil] take:1];

    RACSignal *signalOfSignals = [[RACSignal
                                   createSignal:^RACDisposable *(id<RACSubscriber> subscriber){
                                       [subscriber sendNext:errorNotification];
                                       [subscriber sendNext:completeNotification];
                                       [subscriber sendCompleted];
                                       return nil;
                                   }]
                                  flatten];


    __block BOOL hitCompleted = NO;
    __block BOOL hitNext = NO;
    [signalOfSignals
     subscribeNext:^(id val){
         hitNext = YES;
     }
     error:^(NSError *err){
         STFail(nil);
     }
     completed:^{
         hitCompleted = YES;
     }];

    [[NSNotificationCenter defaultCenter] postNotificationName:@"TEST_SUCCESS" object:self];

    STAssertTrue(hitCompleted, nil);
    STAssertTrue(hitNext, nil);
}
4

2 回答 2

11

您可以使用内置运算符执行此操作:

RACSignal *successNotification = [[NSNotificationCenter.defaultCenter
    rac_addObserverForName:SuccessNotification object:nil]
    take:1];

RACSignal *errorNotification = [[NSNotificationCenter.defaultCenter
    rac_addObserverForName:FailureNotification object:nil]
    flattenMap:^(NSNotification *notification) {
        // Convert to a meaningful error somehow.
        NSError *error = …;

        return [RACSignal error:error];
    }];

RACSignal *signal = [RACSignal merge:@[ successNotification, errorNotification ]];

这会为您处理处置,并且更清楚地表明每个通知如何映射到一个值或一个错误。

为什么@[errorNotification, completeNotification].rac_sequence.signal 不与下面的信号创建信号做同样的事情?

与您在示例中创建的信号不同,创建的信号将异步发送其值。

于 2013-08-07T21:50:40.267 回答
3

这样的事情在成功和失败的情况下都对我有用:

RACSignal *signal = [RACSignal createSignal:^RACDisposable *(id<RACSubscriber> subscriber) {
  RACDisposable *success = [[[[NSNotificationCenter defaultCenter]
                            rac_addObserverForName:@"TEST_SUCESS" object:nil]
                            take:1]
                            subscribeNext:^(id x) {
                              [subscriber sendNext:x];
                            } completed:^{
                              [subscriber sendCompleted];
                            }];
  RACDisposable *failure = [[[[NSNotificationCenter defaultCenter]
                            rac_addObserverForName:@"TEST_FAILURE" object:nil]
                            take:1]
                            subscribeNext:^(id x) {
                            [subscriber sendError:
                              [NSError errorWithDomain:@"RAC_TEST" code:1 userInfo:nil]];
                            }];
  return [RACDisposable disposableWithBlock:^{
    [success dispose];
    [failure dispose];
  }];
}];

我用两个一次性用品创建了一个独特的信号。成功信号发送“下一个”和“完成”(take:1对于完成工作很重要)。失败信号发送“错误”。这个想法是使用subscriber发送到块中来正确转发其他两个信号中的事件。

于 2013-08-04T11:12:23.417 回答