2013-08-04 5 views
5

Mam powiadomienie o powodzeniu i powiadomienie o niepowodzeniu otrzymane za pośrednictwem NSNotificationCenter. Napisałem kilka testów, aby dowiedzieć się, jak połączyć sygnały z tych dwóch powiadomień w jeden sygnał, który dostarcza błąd, gdy powiadomienie o awarii trafia, a następnie kończy się po zakończeniu powiadomienia o powodzeniu.Jaki jest preferowany sposób tworzenia sygnału sygnałów, aby połączyć się z sygnałami i zakończyć, gdy wystąpi błąd?

Obecnie kompletne bloki nie zostaną trafione, następnie błąd zostanie trafiony.

Również dodatkowe pytanie dodatkowe: dlaczego @ notacja błędu, pełna notyfikacja] .rac_sequence.signal robią to samo, co sygnał tworzenia sygnału poniżej?

Kod:

-(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

Przypuszczam, że podczas pierwszego testu wysyłacie nazwę powiadomienia jako "TEST", co oznacza "TEST_FAILURE", prawda? – yonosoytu

+0

Tak. To był błąd w moim teście. d'oh. – Jon

Odpowiedz

11

Można to zrobić za pomocą wbudowanych operatorów:

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

ta zajmuje dyspozycji dla was, a bardziej oczywisty wskazuje, w jaki sposób każdy z powiadomień są odwzorowywane na wartości lub błędu.

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

Utworzony sygnał wyśle ​​swoje wartości asynchronicznie, w przeciwieństwie do sygnału utworzonego w tym przykładzie.

3

Coś jak to działa na mnie w obu przypadkach sukces i porażka:

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

utworzyć unikalny sygnał z obu jednorazowych. Sygnały sukcesu wysyłają "następny" i "zakończony" (take:1 jest ważny dla ukończonych do pracy). Sygnał awarii wysyła "błąd". Pomysł polega na wysłaniu do bloku subscriber w celu prawidłowego przekazania zdarzeń z pozostałych dwóch sygnałów.

+0

Dzięki za odpowiedź ... Jedyną zmianą jest to, że spłaszczam zmapował sygnał powiadomienia o awarii na [błąd RACSigna:] zamiast subskrybować następny. Po prostu zasubskrybuję błąd i przekazuję go dalej. – Jon

+0

Popatrz na odpowiedź Justina na to pytanie. Jego odpowiedź nie wymagała wyraźnego subskrybenta, który jest zawsze lepszy. – yonosoytu

Powiązane problemy