2010-11-08 6 views
38

Estoy intentando pasar un formulario NSDictionary a UIView a un UIViewController usando NSNotificationCenter. El diccionario funciona bien en el momento en que se envía la notificación, pero en el método de recepción no puedo acceder a ninguno de los objetos en el diccionario.Cómo pasar un NSDictionary con postNotificationName: object:

Así es como estoy creando el diccionario y la publicación de la notificación ...

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

En el UIViewController estoy fijando el observador ...

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

Para propósitos de prueba se ve como hotSpotMore esto ...

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

El primer NSLog funciona bien mostrando los contenidos de th diccionario electrónico El segundo registro arroja la siguiente excepción ...

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

No entiendo por qué no puedo acceder a ningún objeto en el diccionario pasado.

Gracias de antemano por cualquier ayuda.

John

Respuesta

110

La primera NSLog funciona bien mostrando el contenido del diccionario. El segundo registro lanza la siguiente excepción ...

El programa intenta engañar a usted, sólo se ve como es su diccionario porque su diccionario está dentro de la notificación. De la excepción, puede ver que su objeto en realidad es de una clase llamada NSConcreteNotification.
Esto se debe a que el argumento de un método de notificación siempre es un objeto NSNotification. esto funcionará:

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

al igual que una pista: el objeto es por lo general el objeto que envía la notificación, usted debe enviar su NSDictionary como userInfo.
creo que mejoraría su código si desea hacerlo de esta manera:

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


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

El parámetro objeto se utiliza para distinguir entre los diferentes objetos que pueden enviar una notificación.
Digamos que tiene dos objetos HotSpot diferentes que pueden enviar la notificación. Cuando configura el object en addObserver:selector:name:object:, puede agregar un observador diferente para cada uno de los objetos. El uso de nil como parámetro del objeto significa que se deben recibir todas las notificaciones, independientemente del objeto que envió la notificación.

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

Gran !! Gracias que funcionó. Veo que no leí los Temas de programación de notificaciones con suficiente cuidado. – user278859

+8

+1 para que el programa se vuelva sensible e intente engañarte :) –

+0

Publicación antigua, pero sigue siendo muy valiosa. ¡Gracias por eso! Solo una nota rápida: userInfo: tomará un NSDictionary. Si intenta pasar un objeto diferente, deberá insertarlo en un diccionario. – Alex

3

El método Matthias está hablando y el que yo creo que se debe utilizar es

postNotificationName:object:userInfo: 

Donde objeto es el remitente y userInfo es su diccionario.

4

Esta es la mejor manera de pasar los datos del diccionario con NSNotification.

mensaje de notificación:

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

Añadir observador de la manija de la notificación.

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

Método Put Notification Handler.

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

espero, esta solución le ayudará a

+4

Seguí este código y no funcionó porque el tipo de argumento debería ser NSNotification y no NSDictionary – ericraio

+0

Por favor, compruebe su código. Si comparte su código, entonces puedo ayudarlo. El código anterior está funcionando en mis pocas aplicaciones. –

+0

No funciona para mí también, sourceDictionary está siempre vacío –

Cuestiones relacionadas