2010-11-08 14 views
38

J'essaie de passer un NSDictionary à partir d'un UIView à un UIViewController en utilisant NSNotificationCenter. Le dictionnaire fonctionne correctement au moment de la publication de la notification, mais dans la méthode de réception, je ne peux accéder à aucun des objets du dictionnaire.Comment passer un NSDictionary avec postNotificationName: objet:

Voici comment je crée le dictionnaire et l'affichage de la notification ...

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

Dans le UIViewController je suis en train de l'observateur ...

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

Pour des fins de test hotSpotMore ressemble ce ...

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

Le premier NSLog fonctionne bien afficher le contenu de e dictionnaire. Le deuxième journal jette l'exception suivante ...

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

Je ne comprends pas pourquoi je ne peux pas accéder à tous les objets dans le dictionnaire passé.

Merci d'avance pour toute aide.

John

Répondre

110

La première NSLog fonctionne très bien afficher le contenu du dictionnaire. Le deuxième journal jette l'exception suivante ...

Le programme essaie de vous tromper, il ressemble est votre dictionnaire parce que votre dictionnaire est à l'intérieur de la notification. De l'exception, vous pouvez voir que votre objet provient réellement d'une classe nommée NSConcreteNotification. Ceci est dû au fait que l'argument d'une méthode de notification est toujours un objet NSNotification. cela fonctionne:

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

comme un indice: l'objet est généralement l'objet qui envoie la notification, vous devez envoyer votre NSDictionary InfoUtil.
Je pense que cela améliorerait votre code si vous le feriez comme ceci:

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


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

Le paramètre d'objet est utilisé pour distinguer entre les différents objets qui peuvent envoyer une notification. Supposons que vous ayez deux objets HotSpot différents pouvant envoyer la notification. Lorsque vous définissez object dans addObserver:selector:name:object:, vous pouvez ajouter un observateur différent pour chacun des objets. L'utilisation de nil en tant que paramètre d'objet signifie que toutes les notifications doivent être reçues, quel que soit l'objet qui a envoyé la notification.

E.g:

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 
} 
+0

Great !! Merci ça a marché. Je vois que je n'ai pas lu assez attentivement les sujets de programmation de notification. – user278859

+8

+1 pour le programme devenant sensible et essayant de vous tromper :) –

+0

Ancien poste, mais toujours très précieux. Merci pour cela! Juste une petite note: userInfo: prendra un NSDictionary. Si vous essayez de passer un objet différent, vous devrez l'insérer dans un dictionnaire. – Alex

3

La méthode Matthias parle et celui que je pense que vous devriez utiliser est

postNotificationName:object:userInfo: 

Où objet est l'expéditeur et userInfo est votre dictionnaire.

4

C'est le meilleur moyen de transmettre vos données de dictionnaire avec NSNotification.

Notification post:

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

Ajouter Observer pour manipuler la notification.

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

Méthode de gestionnaire de notifications.

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

je l'espère, cette solution vous aidera à

+4

J'ai suivi ce code et cela n'a pas fonctionné pour moi parce que le type d'argument devrait être NSNotification et non NSDictionary – ericraio

+0

Veuillez vérifier votre code. Si vous partagez votre code, je peux vous aider. Au-dessus du code fonctionne dans mes quelques applications. –

+0

Ne fonctionne pas pour moi aussi, le sourceDictionary est toujours vide –