2011-01-19 10 views
4

メッセージを送信する必要があります(メッセージを送信するクラスのインスタンスを作成する)コントロールクラスにメッセージを渡す必要があります。 「NSNotificationは」彼らが何であるか、クラス/関係なく、どこの、メッセージのすべての種類を渡すことができるように宣伝している場合ばかげているグローバル(することができません。前置きのでNSNotification addObserver:someOtherClass

...

( Say ClassBから呼び出す)

ClassAはClasのインスタンスを作成しますsBの

ClassBで今

は、私は愚かな何かをする場合、これは今、申し訳ありませんが、私は含まれていても、"#import "ClassA.h" をコンパイルしませんバックClassA

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

までのボタンの押下に関するメッセージを渡す必要があります以下のように、その後、

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

とは、それはコンパイルが、私のようになりますaddObserver:classa中にClassAのこの新しく作成されたインスタンスを使用します私はそれを知っていましたが、驚くほどこの種のコードは、Iphoneプログラミングの書籍で流行しています...だから、私はとにかくそれを試みました。

しかし、私はClassAでこの機能を入れて、それが呼び出されますが、スタックダンプunrecognized selector sent to instance が発生したり、addObserver:selfを使用しますaddObserver:ClassB を使用している場合。私は右のそれを得る場合、私はXcodeのを削除し、vimのに戻って、古き良き「C」コールバックを使用するように誘惑しています

...

答えて

9

だから、あなたはClassBのインスタンスを作成しますClassAを持っています。それらのインスタンスは、それについて何も知らずに、ClassAに直接通知を送信する必要があります。

これが正しい場合、NSNotificationCenterは必要なものです。 ClassA実装で

はこのようinitialializeメソッドを追加:あなたは、それをすべてまとめると

@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 

@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のインスタンスのみがその名前を使用して、通知を投稿する必要がありますNSNotificationCenterを使用している場合、通知の受信者について何も知る必要はありません。実際には、同じ通知を受信するのと同じ数のオブジェクトを登録することができ、通知オブジェクトを受信すると、それぞれが適切なメソッド(addObserverで指定)を呼び出します。

クラスオブジェクトをクラスオブジェクトとしてではなくオブザーバとして追加する場合は、そのインスタンスのdeallocメソッドで[[NSNotificationCenter defaultCenter] removeObserver:self]を呼び出す必要があります。

+1

偉大な答え....多くのありがとう! – chinasailor

1

ここにいくつかの問題があります。

まず、クラスとインスタンスを同じ意味で使用するのをやめてください。あなたのクラスとインスタンスが表すものの合理的な精神モデルがあり、それが責任あるものになるまでは、一般的にどのOOPをいつ使うべきか、さまざまな混乱があります。

NSNotificationCenterを使用すると、特定のクラスのインスタンス(特定のオブジェクト)を特定の通知のオブザーバーとして登録できます。オブザーバーとして登録するには、オブジェクトを認識して参照する必要があります。

第2に、それぞれのクラスとそのインスタンス化されたオブジェクトが何を担当するのかを検討する必要があります。彼らが知るべきこと、知る必要のないこと、そして彼らがどのようにコミュニケーションできるか。

ClassAのインスタンスとしてObjectAを作成し、ClassBのインスタンスであるObjectBを作成するとします。今すぐObjectAObjectBを認識していますが、AはBを作成したばかりなので、Bへの参照が容易です。ObjectBはまだ認識していませんObjectA; Bが作成されましたが、どのオブジェクトか、そのオブジェクトがどのインスタンスであるかを知る必要はありません。もしObjectBObjectAと通信できるようにしたいのであれば、いくつかの選択肢があります。

  1. 委任:バックObjectAを指すようにObjectBにプロパティを設定ObjectAは、今、Bは直接にメッセージを送ることができます。今はあなたの2つのオブジェクトが一緒に結合されているので、両方とも有用で問題になる可能性があります。
  2. 通知:ObjectBは通知を送信できます。ObjectAは通知を監視できます。 BはAがこれらの通知を観察していることを知る必要はなく、AはBから発信された通知(それは可能だが)を知る必要はない。これらのオブジェクトは非常に緩やかに結合されており、アプリケーションについて多くのことを意識することなく変更することができます。

ObjectAが通知をリッスンする場合は、オブザーバとして追加することはAの責任です。 BはAを認識していないので、BがAを観察者にすることはできません。 Aの作成者は、そのオブジェクトがAへの参照を持っている可能性がありますが、Aの子どもはAへの参照を与えない限りできません。

アレックスのように見えます。

+0

これは大きな説明です。 @chinasailorは、Cocoaフレームワークが提供するそれぞれの特定のテクノロジーを使用するベストプラクティスを習得してください。私はちょうど彼にすぐに問題を解決するための素早いスニペットを与えた: –

+0

再び、アレックスに多くのおかげさ...しかし、ちょうどジョナを指摘するには、それはすべてのコアに言語assmに分解し、あなたObject-Cで行われているように "オブジェクト"を実装する方法、またはポインタを* typedef structs *とすることでC言語で手動で作成する方法は、プログラマがあなたにとって使いやすいようにする方法ですあなたのデータ、コード、または好きな場合、Objs .... – chinasailor

+0

@chinasailor私はあなたが作ろうとしているあらゆる点を把握していないのが怖いです。私が議論している構造は抽象であるが、それはそれらを交換可能にしないということに同意する。 – Jonah

関連する問題