2013-08-04 18 views
5

NSNotificationCenter aracılığıyla gelen başarılı bir bildirim ve hata bildirimi var. Bu iki bildirimden gelen sinyallerin, başarısızlık bildirimi başladığı sırada bir hata veren bir sinyale ve bir sonraki başarı bildirimi bittiğinde tamamıyla tamamlanmasının nasıl bir araya getirileceğine karar vermek için bazı testler yazdım.Sinyalleri birleştirmek ve tamamlandığında veya hata yaptığında tamamlamak için sinyal sinyali oluşturmanın tercih edilen yolu nedir?

Halihazırda tüm bloklar vurulmayacak, bir sonraki ve hata yakalanmayacaktır. Ayrıca, ikincil ikramiye sorusu: neden @ [errorNotification, completeNotification] .rac_sequence.signal, aşağıdaki sinyal oluşturma sinyaliyle aynı şeyi yapıyor?

Kodu: Böyle

-(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); 
} 
+0

İlk testinizde bildirim adını sadece “TEST” olarak gönderdiğinizde “TEST_FAILURE” demek istediniz, değil mi? – yonosoytu

+0

Evet. Bu benim testimde bir hataydı. oh d'. – Jon

cevap

11

Sen yerleşik operatörler ile yapabilirsiniz:

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 ]]; 

Bu sizin için elden ilgilenir ve daha açıkçası bildirimlerin her bir değer ya da bir hata nasıl eşlendiği gösterir.

why doesn't @[errorNotification, completeNotification].rac_sequence.signal do the same thing as the signal of signal creation below?

Oluşan sinyal, örneğinizde oluşturduğunuz sinyalin aksine, zaman uyumsuz olarak değerlerini gönderir.

3

şey hem başarı ve başarısızlık durumlarında benim için çalışıyor:

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]; 
    }]; 
}]; 

ben hem tek kullanımlık ile eşsiz bir sinyal yaratır. Başarı sinyalleri “sonraki” ve “tamamlandı” mesajlarını gönderir (tamamlanan çalışma için take:1 önemlidir). Hata sinyali “hata” mesajını gönderir. Buradaki fikir, diğer iki sinyaldeki olayları doğru bir şekilde iletmek için bloğa gönderilen subscriber kullanıyor.

+0

Cevabınız için teşekkürler ... Tek değişiklik, hata bildirim sinyalini [RACSigna error:] ile eşleştirmekteyim. – Jon

+0

Bu soruya Justin cevabına bakın. Onun cevabı, her zaman daha iyi olan açık bir aboneye gerek duymadı. – yonosoytu

İlgili konular