web-dev-qa-db-ja.com

postNotificationName:objectでNSDictionaryを渡す方法:

NSNotificationCenterを使用して、NSDictionaryフォームからUIViewControllerにUIViewControllerを渡そうとしています。辞書は通知が投稿された時点で正常に機能しますが、受信メソッドでは辞書内のオブジェクトにアクセスできません。

辞書を作成して通知を投稿する方法は次のとおりです...

itemDetails = [[NSDictionary alloc] initWithObjectsAndKeys:@"Topic 1", @"HelpTopic", nil];
    [[NSNotificationCenter defaultCenter] postNotificationName:@"HotSpotTouched" object:itemDetails];

UIViewControllerでは、オブザーバーを設定しています...

[[NSNotificationCenter defaultCenter] addObserver:self
                                         selector:@selector(hotSpotMore:)
                                             name:@"HotSpotTouched"
                                           object:nil];

テスト目的では、hotSpotMoreは次のようになります...

- (void)hotSpotMore:(NSDictionary *)itemDetails{
      NSLog(@"%@", itemDetails);
      NSLog(@"%@", [itemDetails objectForKey:@"HelpTopic"]);    
}

最初のNSLogは、ディクショナリのコンテンツを正常に表示します。 2番目のログは次の例外をスローします...

 [NSConcreteNotification objectForKey:]: unrecognized selector sent to instance 0x712b130

渡された辞書のオブジェクトにアクセスできない理由がわかりません。

助けてくれてありがとう。

ジョン

38
user278859

最初のNSLogは、ディクショナリのコンテンツを正常に表示します。 2番目のログは次の例外をスローします...

プログラムはあなたをだまそうとしますが、辞書は通知の中にあるため、辞書のように見えます。例外から、オブジェクトが実際にNSConcreteNotificationという名前のクラスからのものであることがわかります。
これは、notification-methodの引数が常にNSNotification-objectであるためです。これは動作します:

- (void)hotSpotMore:(NSNotification *)notification {
      NSLog(@"%@", notification.object);
      NSLog(@"%@", [notification.object objectForKey:@"HelpTopic"]);    
}

ヒントとして:オブジェクトは通常、通知を送信するオブジェクトであるため、NSDictionaryをuserInfoとして送信する必要があります。
次のようにするとコードが改善されると思います。

NSNotificationCenter *center = [NSNotificationCenter defaultCenter];
[center postNotificationName:@"HotSpotTouched" object:self userInfo:itemDetails];


- (void)hotSpotMore:(NSNotification *)notification {
      NSLog(@"%@", notification.userInfo);
      NSLog(@"%@", [notification.userInfo objectForKey:@"HelpTopic"]);    
}

Objectパラメーターは、通知を送信できるさまざまなオブジェクトを区別するために使用されます。
両方とも通知を送信できる2つの異なるHotSpotオブジェクトがあるとします。 addObserver:selector:name:object:objectを設定すると、オブジェクトごとに異なるオブザーバーを追加できます。オブジェクトパラメータとしてnilを使用すると、通知を送信したオブジェクトに関係なく、すべての通知を受信する必要があります。

例えば:

FancyHotSpot *hotSpotA;
FancyHotSpot *hotSpotB;

// notifications from hotSpotA should call hotSpotATouched:
[[NSNotificationCenter defaultCenter] addObserver:self 
       selector:@selector(hotSpotATouched:) name:@"HotSpotTouched" 
       object:hotSpotA]; // only notifications from hotSpotA will be received

// notifications from hotSpotB should call hotSpotBTouched:
[[NSNotificationCenter defaultCenter] addObserver:self 
       selector:@selector(hotSpotBTouched:) name:@"HotSpotTouched" 
       object:hotSpotB]; // only notifications from hotSpotB will be received

// notifications from all objects should call anyHotSpotTouched:
[[NSNotificationCenter defaultCenter] addObserver:self 
       selector:@selector(anyHotSpotTouched:) name:@"HotSpotTouched" 
       object:nil]; // nil == “any object”, so all notifications with the name “HotSpotTouched” will be received


- (void)hotSpotATouched:(NSNotification *)n {
    // only gets notification of hot spot A
}

- (void)hotSpotBTouched:(NSNotification *)n {
    // only gets notification of hot spot B
}

- (void)anyHotSpotTouched:(NSNotification *)n {
    // catches all notifications
}
110
Matthias Bauch

これは、NSNotificationで辞書データを渡す最良の方法です。

通知の投稿:

 [[NSNotificationCenter defaultCenter] postNotificationName:@"Put Your Notification Name" object:self userInfo:"Pass your dictionary name"];

通知を処理するためのオブザーバーを追加します。

[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(mydictionaryData:)  name:@"Put Your Notification Name" object:nil];

通知ハンドラーメソッドを配置します。

- (void)mydictionaryData::(NSNotification*)notification{
   NSDictionary* userInfo = notification.userInfo;
   NSLog (@"Successfully received test notification! %@", userInfo);}

このソリューションがあなたの助けになることを願っています

4
Amit Singh

Matthiasが話している方法で、あなたが使用すべきだと思う方法は

postNotificationName:object:userInfo:

Objectは送信者で、userInfoは辞書です。

3
Brabbeldas