2013-08-12 9 views
19

Jak mogę utworzyć sygnał z nazwy powiadomienia? Na przykład, chcę iść z:Jak używać Reaktywnego kakao z powiadomieniami

[[NSNotificationCenter defaultCenter] addObserver:self 
             selector:@selector(userDidChange:) 
              name:kTTCurrentUserLoggedOffNotification 
              object:nil]; 

do czegoś podobnego:

[signalForName(kTTCurrentUserLoggedOffNotification) subscribeNext:^(id x){ 
... 
}]; 

Odpowiedz

45

-[NSNotificationCenter rac_addObserverForName:object:] zwraca nieskończoną sygnał. Możesz zapisać się na tym tak

objective-c

[[[[NSNotificationCenter defaultCenter] rac_addObserverForName:UIApplicationDidEnterBackgroundNotification object:nil] 
    takeUntil:[self rac_willDeallocSignal]] 
    subscribeNext:^(id x) { 
    NSLog(@"Notification received"); 
}]; 

Swift

NSNotificationCenter.defaultCenter() 
    .rac_addObserverForName(UIKeyboardWillShowNotification, object: nil) 
    .takeUntil(self.rac_willDeallocSignal()) 
    .subscribeNext { (_) in 
    print("Notification received") 
    } 

Sygnał ten jest jak stwierdzono nieskończona. Jeśli potrzebujesz tego sygnału/Subskrypcja być związana z życia self można dodać takeUntil: z rac_willDeallocSignal tak:

Objective-C

[[[[NSNotificationCenter defaultCenter] rac_addObserverForName:UIApplicationDidEnterBackgroundNotification object:nil] 
    takeUntil:[self rac_willDeallocSignal]] 
    subscribeNext:^(id x) { 
    NSLog(@"Notification received"); 
}]; 

Swift

NSNotificationCenter.defaultCenter() 
    .rac_addObserverForName(UIKeyboardWillShowNotification, object: nil) 
    .takeUntil(self.rac_willDeallocSignal()) 
    .subscribeNext { (_) in 
    print("Notification received") 
    } 
+0

To wydaje się działać, na pewno. Ale jeśli trzeba to zrobić tak, to metoda jest zasadniczo wadliwa. Sygnały działają, dopóki nie ma do nich odniesienia. Jeśli sygnał zostanie zwolniony, należy go wyrzucić, co z kolei spowoduje usunięcie obserwatora. Możesz rozejrzeć się w swoim kodzie, może być silne odniesienie do sygnału, który uniemożliwia jego zwolnienie. Lub jeśli tak nie jest, prosimy o zgłoszenie problemu projektowi, ponieważ moim zdaniem nie jest to oczekiwane zachowanie. – allprog

+4

@allprog [Subskrybenci zachowują swoje sygnały] (https://github.com/ReactiveCocoa/ReactiveCocoa/blob/master/Documentation/MemoryManagement.md) do zakończenia, błędu lub utylizacji. To dlatego nieskończone sygnały mogą być dość gnarly. '-takeUntil:' jest dobrym rozwiązaniem lub czymś podobnym, które deterministycznie kończy sygnał w pewnym punkcie. –

+2

@ JustinSpahr-Summers Dzięki za wyjaśnienie. Wiedziałem, że jestem zbyt chętny, aby wykrzyczeć wilka! Ale jesteś tu, aby mnie poprawić. :) Czy dokumentacja może zawierać te zawiłości? Na przykład. "jest to nieskończony sygnał" i daje wskazówkę do jakiegoś opisu, który pokazuje, co należy wziąć pod uwagę. Będę szczery, ramy wydają się mieć niektóre z tych "pułapek" i byłoby lepiej, gdyby uwypuklono specyfikę zwracanego sygnału w tych przypadkach. – allprog

10

W RACExtensions można znaleźć kategorię NSNotificationCenter (RACSupport). Że ma metodę do tego celu:

- (RACSignal *)rac_addObserverForName:(NSString *)notificationName 
           object:(id)object; 
+1

Ja doświadczam, że to nigdy nie jest usuwane .. Czy musimy sami wyrzucać ten sygnał? – hfossli

+0

Obserwacja jest związana z sygnałem. Jeśli to się uda, to obserwator zostaje usunięty. Czy to możliwe, że masz gdzieś silne odniesienie do sygnału? (To jest podstępna część ObjC :)) – allprog

+2

Znaleziono :) zobacz nową odpowiedź – hfossli

-1

Swift wersja korzystająca z ReactiveCocoa 4.1:

NSNotificationCenter.defaultCenter() 
     .rac_addObserverForName(UIKeyboardWillShowNotification, object: nil) 
     .takeUntil(self.rac_willDeallocSignal()) 
     .subscribeNext { (_) in 
      print("UIKeyboardWillShowNotification") 
     }