2013-08-12 2 views
19

Как я могу создать сигнал из имени уведомления? Например, я хочу, чтобы перейти от:Как использовать реактивное какао с уведомлениями

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

к чему-то вроде:

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

ответ

45

-[NSNotificationCenter rac_addObserverForName:object:] возвращает бесконечный сигнал. Вы можете подписаться на него, как этот

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") 
    } 

Этот сигнал, как указано в бесконечность. Если вам нужен этот сигнал/подписку на обязательность для жизни self вы можете добавить takeUntil: с rac_willDeallocSignal так:

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

Это, похоже, работает, конечно. Но если это нужно сделать так, то метод фундаментально испорчен. Сигналы живут до тех пор, пока не появится ссылка на них. Если сигнал отпускается, тогда он должен быть удален, что, в свою очередь, удаляет наблюдателя. Вы можете посмотреть вокруг в своем коде, может быть сильная ссылка на сигнал, который не позволяет ему освободиться. Или, если это не так, пожалуйста, сообщите о проблеме проекту, поскольку это, по моему мнению, не является ожидаемым поведением. – allprog

+4

@allprog [Подписчики сохраняют свои сигналы] (https://github.com/ReactiveCocoa/ReactiveCocoa/blob/master/Documentation/MemoryManagement.md) до завершения, ошибки или удаления. Вот почему бесконечные сигналы могут быть довольно грубыми. '-takeUntil:' это хорошее решение или что-то подобное, которое детерминистически завершает сигнал в определенной точке. –

+2

@ JustinSpahr-Summers Спасибо за разъяснение. Я знал, что я слишком хочу кричать волка! Но ты должен меня исправить. :) Может ли документация содержать эти тонкости? Например. «это бесконечный сигнал» и дать указатель на некоторое описание, которое показывает, что нужно учитывать. Я буду честен, у структуры, похоже, есть некоторые из этих «ловушек-ловушек», и было бы лучше, если бы были подчеркнуты особенности возвращаемого сигнала в этих случаях. – allprog

10

В RACExtensions вы можете найти NSNotificationCenter (RACSupport) категорию. То есть метод для этой цели:

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

Я чувствую, что это никогда не удаляется .. Нужно ли нам самим распоряжаться этим сигналом? – hfossli

+0

Наблюдение привязано к сигналу. Если это удалено, то наблюдатель удаляется. Может быть, вы где-то держите ссылку на сигнал? (Это сложная часть ObjC :)) – allprog

+2

Обнаружено :) см. Новый ответ – hfossli

-1

Swift версия с использованием ReactiveCocoa 4.1:

NSNotificationCenter.defaultCenter() 
     .rac_addObserverForName(UIKeyboardWillShowNotification, object: nil) 
     .takeUntil(self.rac_willDeallocSignal()) 
     .subscribeNext { (_) in 
      print("UIKeyboardWillShowNotification") 
     } 
Смежные вопросы