NSNotificationCenter one post causes observers to be called twice - iphone

I have the following code:
[[NSNotificationCenter defaultCenter] postNotificationName:kNewsfeedFetchCompleted object:self userInfo:userinfo];
only this, no where else. And here's how I set the observer:
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(newsfeedFetchCompleted:) name:kNewsfeedFetchCompleted object:nil];
question is when I do one post the newsfeedFetchCompleted is called twice.. how is this even possible?

This is possible when your code for addObserver is executed twice. The notification function will be called as many times as it is registered.
So make sure your code for adding observer is executed for once only. So, you can keep it in viewDidLoad or init method.
If you are putting it in viewWillAppear then remove observer in viewWillDisAppear.

before you add observer, make sure you remove the previous observer added.
[[NSNotificationCenter defaultCenter]removeObserver:self];
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(newsfeedFetchCompleted:) name:kNewsfeedFetchCompleted object:nil];

It is possible if you have added the same observer multiple times for the newsfeedFetchCompleted notification. You should match your addObserver calls with removeObserver calls.
For example if you added the observer in viewWillAppear/viewWillDidAppear/ViewDidLoad of a UIViewController, you should remove it in viewWillDisappear/viewDidDisappear/ViewDidUnload.
The corresponding remove call for addObserver, is removeObserver:name:object:
More info can be found in the NSNotificationCenter docs

Related

is removeObserver necessary on dealloc?

In one of my view controller, it adds itself as observer of UITextViewTextDidEndEditingNotification notification, like the following does
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(done:) name:UITextViewTextDidEndEditingNotification object:nil];
Now I am wondering - do I need to do the following when the view controller is dealloc'd
[[NSNotificationCenter defaultCenter] removeObserver:self];
yes, you should always remove any observers when they're being dealloc'd. otherwise the notification center will keep references to the now-dealloc'd objects around and continue to try to forward notifications to them.

Why I cannot receive the Notification

[[NSNotificationCenter defaultCenter] postNotificationName:kNotificationForbidAdvPost object:nil];
I define postNotificationName:kNotificationForbidAdvPost in a .h file
Im my subclass of NSApplication, I import this .h file. And have a observer of this Notification
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(changeToRecordingStatus) name:kNotificationForbidAdvPost object:nil];
I am sure that the observer was added first, and then post the notification.
And I see the [UINotification default] in Debug. It have same memory address in two part of code.
Is there some mistake I have?
Thanks!
The documentation is pretty clear when it states that
The method specified by
notificationSelector must have one and
only one argument (an instance of
NSNotification).
http://developer.apple.com/library/mac/documentation/Cocoa/Reference/Foundation/Classes/NSNotificationCenter_Class/Reference/Reference.html#//apple_ref/doc/uid/20000219-CHDCIGGB
So, I see your selector you are registering is changeToRecordingStatus when it must be changeToRecordingStatus:
- (void) changeToRecordingStatus: (NSNotification *) notification;
I have try that add a arugument, but it is still not worked.
I create a new project and use a no-argument function to response Notification, it is worked normally.
The reason why I cannot receive the Notification is that a removeObserver method was called at one part which I didn't notice.
Thanks for all your reply.

NSNotificationCenter in viewDidLoad: not working

for some reason this code isn't working in viewDidLoad, but will work in viewWillAppear. Any ideas?
[[NSNotificationCenter defaultCenter]
addObserver:self
selector:#selector(wakeUp:)
name:UIApplicationWillEnterForegroundNotification
object:nil];
Thank you
you're definitely sure viewDidLoad is being invoked?
For my case is that I put the removeObserver method inside didReceiveMemoryWarning method, and if I take a picture or do something else, this method fires out of my expect. So, now I always remove notification observer at dealloc stage.

Where should I remove a notification observer?

I set up a notification observer in my view controller's init method like so:
[[NSNotificationCenter defaultCenter]
addObserver:self
selector:#selector(saveState)
name:UIApplicationWillResignActiveNotification
object:nil];
Where is the best place to call removeObserver:name:object: for this notification. I'm currently calling it in my dealloc method, but wanted to know if that might cause problems.
No, you got it right. dealloc is the correct location to remove notification observers (unless you have some specific reason to need to remove the observer earlier).
You can always remove the observer in viewWillDisappear:, or when you are done using it and have no other need for it, you can place it in a function.
If the -saveState only need to execute once when active, then you can removeObserver inside the -saveState.

Determine if UIViewController is closing due to application exit?

Is there a way to test in viewWillDisappear if it's being called because the application is exiting, versus normal ways of it being dismissed? The method applicationWillTerminate in the App Delegate is called after the current view is closed. I want to do different things depending on whether it's being dismissed due to a IBAction or the user clicking the menu button.
Thanks!
You should use observe the UIApplicationWillTerminateNotification in your controller, set a flag, and then check for the flag in your viewWillDisappear implementation.
NSNotificationCenter* defaultCenter = [NSNotificationCenter defaultCenter];
[defaultCenter addObserver:self
selector:#selector(applicationWillTerminate:)
name:UIApplicationWillTerminateNotification
object:nil];
I haven't used it for your purposes yet, but the UIApplicationWillResignActiveNotification notification might occur before applicationWillTerminate is called.
Just throw...
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(applicationWillResign:) name:UIApplicationWillResignActiveNotification object:NULL];
... into your UIViewController to test it out.