2013-08-12 12 views
19

Làm cách nào để tạo tín hiệu ra khỏi tên thông báo? Ví dụ, tôi muốn đi từ:Cách sử dụng Reactive Cocoa với thông báo

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

một cái gì đó như:

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

Trả lời

45

-[NSNotificationCenter rac_addObserverForName:object:] trả về một tín hiệu vô hạn. Bạn có thể đăng ký để nó như thế này

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

Tín hiệu này được như đã nêu vô hạn. Nếu bạn cần tín hiệu này/thuê bao bị ràng buộc để tuổi thọ của self bạn có thể thêm takeUntil: với rac_willDeallocSignal như thế này:

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

Điều này dường như làm việc, chắc chắn. Nhưng nếu nó phải được thực hiện như thế này, thì phương pháp cơ bản là thiếu sót. Tín hiệu sống cho đến khi có một tham chiếu đến chúng. Nếu tín hiệu được giải phóng, sau đó nó sẽ được xử lý mà lần lượt loại bỏ người quan sát. Bạn có thể nhìn xung quanh trong mã của bạn, có thể có một tham chiếu mạnh mẽ đến các tín hiệu mà giữ nó khỏi bị deallocated. Hoặc nếu đây không phải là trường hợp, sau đó xin vui lòng báo cáo một vấn đề cho dự án vì đây không phải là hành vi mong đợi theo ý kiến ​​của tôi. – allprog

+4

@allprog [Người đăng ký giữ lại tín hiệu của họ] (https://github.com/ReactiveCocoa/ReactiveCocoa/blob/master/Documentation/MemoryManagement.md) cho đến khi hoàn thành, lỗi hoặc xử lý. Đó là lý do tại sao các tín hiệu vô hạn có thể nhận được khá gnarly. '-takeUntil:' là một giải pháp tốt, hoặc một cái gì đó tương tự mà xác định kết thúc tín hiệu tại một điểm nhất định. –

+2

@ JustinSpahr-Summers Cảm ơn bạn đã làm rõ. Tôi biết tôi quá háo hức hét lên con sói! Nhưng bạn ở đó để sửa tôi. :) Tài liệu có thể chứa những phức tạp này không? Ví dụ. "đây là một tín hiệu vô hạn" và đưa ra một con trỏ đến một số mô tả cho thấy những gì người ta cần phải xem xét. Tôi sẽ trung thực, khuôn khổ dường như có một số trong những "bẫy bẫy" và nó sẽ là tốt hơn nếu các chi tiết cụ thể của tín hiệu trả về trong những trường hợp này được nhấn mạnh. – allprog

10

Trong RACExtensions bạn có thể tìm thấy những loại NSNotificationCenter (RACSupport). Có một phương pháp cho mục đích này:

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

Tôi trải nghiệm điều này không bao giờ bị xóa .. Chúng tôi có cần tự mình loại bỏ tín hiệu này không? – hfossli

+0

Quan sát được gắn với tín hiệu. Nếu đó là xử lý, sau đó người quan sát được loại bỏ. Nó có thể được rằng bạn đang giữ tham chiếu mạnh mẽ đến các tín hiệu ở đâu đó? (Đây là phần khó khăn của ObjC :)) – allprog

+2

Tìm ra :) xem câu trả lời mới – hfossli

-1

Swift phiên bản sử dụng ReactiveCocoa 4.1:

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