0


Last week I asked this question: Refresh the entire iOS app @Jim advised me to use the notification center. I was not able to figure out how to work with notifications and I was told to ask another question, I tried for the full week to figure it out on my own, so here goes.

I have a view with multiple subviews. One of the subviews is a search bar (not the tableview one, just a custom text box), the user can search for a new person here and the entire app will be updated screen by screen.

When the user taps on the GO button in the search subview I make the call to the server to get all the data. After which I post this notification:

 [self makeServerCalls];

[[NSNotificationCenter defaultCenter] postNotificationName:@"New data" object:Nil];

Now in the init of my parent view controller I have a listener

[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(viewDidLoad) name:@"New data" object:nil];

I know this is most probably wrong, so can anyone explain to me how to use notifications properly in my situation? Or if there is a better way of doing what I want.

Thanks for any help you can give me.

Community
  • 1
  • 1
user1396737
  • 15
  • 1
  • 6
  • You should probably not just recall viewDidLoad. Add a refresh method that will update all your views for you. – James Paolantonio Sep 07 '12 at 21:36
  • @James is correct you really shouldn't call `viewDidLoad` manually - extract the code you want run in response to the notification into a separate method and call it from `viewDidLoad` as needed. But what isn't working? You don't really explain the problem. – Carl Veazey Sep 07 '12 at 21:43
  • Sorry if my question wasn't clear. After following @Jody's answer the problem now is that when I post a notification from my subview, the selector in the parent view is never called. Would you know why that is? – user1396737 Sep 08 '12 at 11:54
  • Make sure you didn't `removeObserver` somewhere else – onmyway133 Jan 28 '15 at 10:10

1 Answers1

3

When you post a notification, it will cause all register observers to be notified. They get notified by having a message sent to them... the one identified by the selector. As mentioned in the comments, you should not use viewDidLoad. Consider this...

- (void)newDataNotification:(NSNotification *notification) {
    // Do whatever you want to do when new data has arrived.
}

In some early code (viewDidLoad is a good candidate):

[[NSNotificationCenter defaultCenter]
    addObserver:self
       selector:@selector(newDataNotification:)
           name:@"New data"
         object:nil];

That's a terrible name, BTW. Oh well. This registration says that your self object will be sent the message newDataNotification: with a NSNotification object whenever a notification is posted with the name "New data" from any object. If you want to limit which object you want to receive the message from, provide a non-nil value.

Now, when you send the notification, you can do so simply, like you did in your code:

[[NSNotificationCenter defaultCenter] postNotificationName:@"New data" object:nil];

and that will make sure (for practical purposes) that [self newDataNotification:notification] is called. Now, you can send data along with the notification as well. So, let's say that the new data is represented by newDataObject. Since you accept notifications from any object, you could:

[[NSNotificationCenter defaultCenter]
    postNotificationName:@"New data"
                  object:newDataObject];

and then in your handler:

- (void)newDataNotification:(NSNotification *notification) {
    // Do whatever you want to do when new data has arrived.
    // The new data is stored in the notification object
    NewData *newDataObject = notification.object;
}

Or, you could pass the data in the user info dictionary.

[[NSNotificationCenter defaultCenter]
    postNotificationName:@"New data"
                  object:nil
                userInfo:@{
                          someKey : someData,
                       anotherKey : moreData,
                          }];

Then, your handler would look like this...

- (void)newDataNotification:(NSNotification *notification) {
    // Do whatever you want to do when new data has arrived.
    // The new data is stored in the notification user info
    NSDictionary *newData = notification.userInfo;
}

Of course, you could do the same thing with the block API, which I prefer.

Anyway, note that you must remove your observer. If you have a viewDidUnload you should put it in there. In addition, make sure it goes in the dealloc as well:

- (void)dealloc {
    // This will remove this object from all notifications
    [[NSNotificationCenter defaultCenter] removeObserver:self];
}
Jody Hagins
  • 27,943
  • 6
  • 58
  • 87
  • Thank you for the response. But it still isn't working for me. How would the parent view know that a notification has been posted? is this automatic? I believe that my notification selector is never called. – user1396737 Sep 08 '12 at 11:48
  • Yes, it's "automatic." Make sure you use the right selector. `foo` is different from `foo:`. Also, you can set a breakpoint and trace the progress. If you continue to have problems, you need to post code that is not working. – Jody Hagins Sep 09 '12 at 11:45