How to pass a NSDictionary with postNotificationName:object:

43,663

Solution 1

The first NSLog works fine displaying the contents of the dictionary. The second log throws the following exception...

The program tries to trick you, it just looks like it is your dictionary because your dictionary is inside the notification. From the exception you can see that your object actually is from a class named NSConcreteNotification.
This is because the argument of a notification-method is always a NSNotification-object. this will work:

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

just as a hint: the object is usually the object which sends the notification, you should send your NSDictionary as userInfo.
I think it would improve your code if you would do it like this:

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


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

The object parameter is used to distinguish between the different objects that can send a notification.
Let’s say you have two different HotSpot objects that can both send the notification. When you set the object in addObserver:selector:name:object: you can add a different observer for each of the objects. Using nil as the object parameter means that all notifications should be received, regardless of the object that did send the 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
}

Solution 2

This is the best way to pass your dictionary data with NSNotification.

Post Notification :

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

Add Observer for Handle the Notification.

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

Put Notification Handler method.

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

I hope, this solution will help you

Solution 3

The method Matthias is talking about and the one I think you should be using is

postNotificationName:object:userInfo:

Where object is the sender and userInfo is your dictionary.

Share:
43,663
user278859
Author by

user278859

Updated on February 01, 2020

Comments

  • user278859
    user278859 over 4 years

    I am trying to pass an NSDictionary form a UIView to a UIViewController using NSNotificationCenter. The dictionary works fine at the time the notification is posted, but in the receiving method I am unable to access any of the objects in the dictionary.

    Here is how I am creating the dictionary and posting the notification...

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

    In the UIViewController I am setting the observer...

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

    For testing purposes hotSpotMore looks like this...

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

    The first NSLog works fine displaying the contents of the dictionary. The second log throws the following exception...

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

    I don't understand why I cannot access any objects in the passed dictionary.

    Thanks in advance for any help.

    John

  • user278859
    user278859 over 13 years
    Great!! Thanks that worked. I see that I did not read the Notification Programming Topics carefully enough.
  • Lescai Ionel
    Lescai Ionel over 11 years
    +1 for the program becoming sentient and trying to trick you :)
  • ericraio
    ericraio about 11 years
    I followed this code and it didn't work for me because the argument type should be NSNotification and not NSDictionary
  • Amit Singh
    Amit Singh over 10 years
    Please check your code. If you share your code then i can help you. Above code is working in my few applications.
  • Travis M.
    Travis M. over 9 years
    Doesn't work for me as well, the sourceDictionary is always empty
  • Alex
    Alex over 7 years
    Old post, but still very valuable. Thanks for it! Just a quick note: userInfo: will take a NSDictionary. If you are trying to pass a different object you will have to insert in a dictionary.