2011-01-19 49 views
4

我需要將消息傳遞給控制類(它創建將發送消息的類的實例)所以,我無法直接引用類文件名稱全球(這是荒謬做的,如果「NSNotification」通告到能夠通過各種消息,無論在哪裏/它們是什麼類。NSNotification addObserver:someOtherClass

所以事不宜遲......

(從Say ClassB調用)

ClassA創建Clas實例膽紅

現在ClassB,我需要就按下按鈕的消息傳回多達ClassA

(insdie ClassB) 
- (void)viewDidLoad 
{ 
    [[NSNotificationCenter defaultCenter] addObserver:ClassA 
             selector:@selector(doLoginAction)  
             name:@"SomeButton" 
             object:nil]; 
    [super viewDidLoad]; 
} 

這將無法編譯,甚至當我有,對不起,"#import "ClassA.h" 現在,如果我做了什麼愚蠢的像,

ClassA *classa = [[ClassA alloc]init]; 

,然後使用這個新創建的addObserver:classa ClassA的它將編譯的實例,但我思想,絕對不會做任何事情......(我知道,但令人驚訝的是,這種代碼在Iphone編程書籍中很流行......)所以我嘗試了它。

但如果我把這個功能ClassA和使用addObserver:ClassB 它會被調用,但會導致堆棧轉儲unrecognized selector sent to instance 或使用addObserver:self

我忍不住要刪除Xcode和回到vim和使用好老的「C」回調...

回答

9

所以,如果我得到它的權利,你有一個ClassA這就造成ClassB實例。這些實例反過來應該直接發送通知給ClassA,而不知道任何事情。

如果這是正確的,那麼NSNotificationCenter正是你所需要的。

ClassA實現添加initialialize方法是這樣的:

@implementation ClassA 

+ (void)initialize 
{ 
    [[NSNotificationCenter defaultCenter] 
     addObserver:self 
      selector:@selector(YourSelector:) 
       name:@"YourNotificationName" 
      object:nil]; 
} 

+ (void)YourSelector:(NSNotification *)notification 
{ 
    NSDictionary *userInfo = [notification userInfo]; 

    // ... 
} 

// ... 

@end 

然後,ClassB實例應該只使用它的名字張貼他們的通知:

@implementation ClassB 

- (void)postNotification 
{ 
    NSDictionary *userInfo = ...; // may be nil 
    [[NSNotificationCenter defaultCenter] 
     postNotificationName:@"YourNotificationName" 
           // the same name is used in the `addObserver` call 
           // in the previous code snippet 
         object:nil 
        userInfo:userInfo]; 
} 

// ... 

@end 

總結這一切,你做的如果您使用的是NSNotificationCenter,則無需瞭解有關通知接收方的任何信息。實際上,您可以訂閱儘可能多的對象以便接收相同的通知,並且每個對象都會在收到通知對象時調用其適當的方法(在addObserver中指定)。

請記住,在將類實例添加爲觀察者而不是類對象本身時,應該在該實例的dealloc方法中調用[[NSNotificationCenter defaultCenter] removeObserver:self]

+1

很好的回答....非常感謝! – chinasailor 2011-01-19 07:43:41

1

我在這裏看到一些問題。

首先,您需要停止嘗試交替使用類和實例。除非你對你的類和實例代表什麼以及它們負責什麼有一個合理的心智模型,否則在什麼時候使用哪一個和OOP的時候會有各種各樣的困惑。

NSNotificationCenter允許您將類的特定實例(單個對象)註冊爲特定通知的觀察者。您需要了解並參考觀察對象,才能將其註冊爲觀察者。

其次,你需要考慮你的每個類,以及它們的實例化對象所負責的。他們應該知道什麼,他們不需要知道什麼,以及他們如何溝通。

我們假設您創建ObjectA作爲ClassA的實例,並創建了ObjectB,它是ClassB的實例。現在ObjectA知道ObjectB,畢竟A剛剛創建B,所以A很容易引用B。ObjectB還不知道ObjectA; B被創建,但它不需要知道哪個對象,甚至哪個對象是什麼類的實例。如果你想ObjectB能夠與ObjectA溝通,你有幾個選項。

  1. 團:ObjectA上設置ObjectB一個屬性來指回ObjectA,現在乙可以將消息發送至A直接。現在你的兩個對象被耦合在一起,這可能是有用的和有問題的。
  2. 通知:ObjectB可以發佈通知,ObjectA可以觀察通知。 B不需要知道A正在觀察那些通知,A不需要知道通知是由B發起的(儘管它可以)。這些對象非常鬆散地耦合在一起,您可以在應用程序中改變很多事情,而無需知道它們。

重要的是,如果ObjectA要偵聽通知,那麼它有責任將自己添加爲觀察者。因爲B不知道A,所以B不可能讓A成爲觀察者。 A的創建者可能會因爲該對象會提及A,但A的孩子不能,除非他們被給予對A的一些參考。

Alex看起來像一個很好的答案,所以希望這一切都會有用。

+0

這是一個很好的解釋。 @chinasailor絕對應該嘗試熟悉使用Cocoa框架提供的每種特定技術的最佳實踐。我只是給了他一個快速的片段,以解決在灣問題的立即問題:) – 2011-01-19 07:56:26