I'm using an addObserver like so:
[[NSNotificationCenter defaultCenter] addObserver: self selector: #selector(notificationReceived:) name:nil object: nil];
Everything works well, but I thought it might be good form to remove the observer when I no longer needed it... I found that I needed to use this line:
[[NSNotificationCenter defaultCenter] removeObserver:self name:#"observerName" object:nil];
Problem is, when I change my addObserver line to include the name so that the removeObserver will know which observer to remove, the notifications no longer get called. This line is run but ignored when the name is added:
[[NSNotificationCenter defaultCenter] addObserver: self selector: #selector(notificationReceived:) name:#"observerName" object: nil];
I can set the name back to nil and it works again.
Anybody know what I'm doing wrong here?
Thanks!
I think you might be mistaken as the what the parameters mean.
The name: tells the system which notifications you want to be informed about.
self is the actual observer, so when you removeOberserver:self you will stop to receive any notifications.
You should read the documentation carefully again as to which have which meaning:
https://developer.apple.com/library/mac/#documentation/Cocoa/Reference/Foundation/Classes/NSNotificationCenter_Class/Reference/Reference.html#//apple_ref/doc/uid/20000219-SW1
For an example, see How to create a class to send and receive events through NSNotificationCenter in Objective-C?
Related
I usually use NSNotification like the sample below:
In viewDidLoad:
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(foo:) name:kName1 object:nil];
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(bar:) name:kName2 object:nil];
In viewDidUnload and dealloc:
[[NSNotificationCenter defaultCenter] removeObserver:self];
But a friend told me that I should not use [[NSNotificationCenter defaultCenter] removeObserver:self]; because it will remove all the observers including the super class's . He suggested me to use the following code to remove observer one by one.
[[NSNotificationCenter defaultCenter] removeObserver:self name:kName1 object:nil];
[[NSNotificationCenter defaultCenter] removeObserver:self name:kName2 object:nil];
I've checked the ASIHttpRequest library's code ( https://github.com/pokeb/asi-http-request ). It follows my friends' suggestion.
I want to know if my friend is right or not? In my opinion, since the current instance will be unload or dealloc, the super class's notification is also useless. And is there any system UIViewController subclass use notification?
Your friend is 100% correct. Though, it does not matter if you remove all notification observations in dealloc.
You mentioned viewDidUnload, and there the case is completely different, because the unloaded object will stay alive, and you don't know when the notification observations of the superclass are added again. If they are added in viewDidLoad you won't have a problem. If they are added in an init method you just lost a bunch of important notification observations.
Removing observations with specific names is good practice and should be done from the beginning.
When you want to remove all notification you use,
[[NSNotificationCenter defaultCenter] removeObserver:self];
If you want to remove a particular notification you use,
[[NSNotificationCenter defaultCenter] removeObserver:self name:kName1 object:nil];
When you no longer in need of any notification the first approach is simple.
As the object is going away, it's safe to use [[NSNotificationCenter defaultCenter] removeObserver:self]; in the dealloc method.
In ViewDidUnload method, you'd better remove each observer one by one as a reference to the controller is still around (and your corresponding viewDidLoad should add them all back in).
I use the first way, I never thought about whether it was right or not. If dealloc is being called, then the object (super as well) is going to be deallocated anyway. What you definitely DON'T want is the NSNotification being sent to a deallocated instance.
i am sending NSSNotifcation to another view controller in iPhone app but its observer method getting notified two times how its possible can any one guide me
i have use this code to post notification
[[NSNotificationCenter defaultCenter] postNotificationName:#"updateStatusOnFacebook" object:nil userInfo:nil];
and added observer
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(postToWall) name:#"updateStatusOnFacebook" object:nil];
Have you added the observer twice?
Which method are you calling addObserver:selector:object: in? If it's in viewWillAppear then this might be called more than once.
Your method will be called the same number of times that you have added an observer.
Try this:
[[NSNotificationCenter defaultCenter] removeObserver:self name:#"updateStatusOnFacebook" object:nil];
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(postToWall) name:#"updateStatusOnFacebook" object:nil];
The other reason is that you might just be sending the notification twice :)
I had the same problem crop up, and read this question, but could only find the one call to add the observer anywhere in the project.
In our case, the observer was being added twice because the method the line was in was being called twice.
Make sure you step through your code, breaking on your addObserver:selector:name:object call, to ensure that you don't have an unexpected extra execution path to that call.
Is there any way to break on the NSNotificationCenter posting a Note with a certain name? I have a class that for some reason don't receive en expected note...
Edit for clarification:
I have added an observer for the MPMoviePlayerPlaybackDidFinishNotification, but for some reason it seems as if the Notification isn't sent as expected. A normal fault here is that my object for some reason has unsubscribed itself as an observer (even though I find my code on that part to look valid). So, my intention was whether or not it is possible to break on the NSNotificationCenter actually passing on a NotificationName of a certain type, in this case MPMoviePlayerPlaybackDidFinishNotification...
Add a breakpoint in Xcode with the name "-[NSNotificationCenter postNotification:]" using the box displayed in the screenshot. Just remember that this will stop for every notification posted, so you might want to have the debugger log the arguments and autocontinue.
You can put break point in methods which you call for certain event.
e.g.
NSNotificationCenter *nc = [NSNotificationCenter defaultCenter];
[nc addObserver:self selector:#selector(keyboardWillShow:) name: UIKeyboardWillShowNotification object:nil];
[nc addObserver:self selector:#selector(keyboardWillHide:) name: UIKeyboardWillHideNotification object:nil];
here you can use break point in keyboardWillShow and keyboardWillHide method which call on the time of keyboard events.
So you need to specify valid event name and valid object name.
In case of textfield as an object you use like this
NSNotificationCenter *notificationCenter = [NSNotificationCenter defaultCenter];
[notificationCenter addObserver:self
selector:#selector (handle_TextFieldTextChanged:)
name:UITextFieldTextDidChangeNotification
object:self.lockTextField];
so i think you need to add notification in right way.
this solution
Receive iPhone keyboard events
offers a way to capture the keypress event using notification center.
[[NSNotificationCenter defaultCenter] addObserver: self selector: #selector(keyPressed:) name: UITextFieldTextDidChangeNotification object: nil];
[[NSNotificationCenter defaultCenter] addObserver: self selector: #selector(keyPressed:) name: UITextViewTextDidChangeNotification object: nil];
........
-(void) keyPressed: (NSNotification*) notification
{
NSLog([[notification object]text]);
}
It works ok, but for every key that is been pressed from the keyboard the keyPressed function gets called 3 times.
Is this normal or am i doing something wrong?
Teo
The notification should only appear once per key pressed. At least that is what I get when testing. The only thing I can think of is that you are calling addObserver:selector:name:object: three times.
Perhaps you are doing it in several view controllers and forget to call removeObserver:name:object:?
Or you are calling addObserver:selector:name:object: in a function that gets called several times? viewDidLoad is normally a good place to put code like this.
I am looking at a project which was provided me by my organization, for study.
The problem is that in this project I found some code which I never saw before.
Please tell me why the following code is written.
-(void)notifications
{
[[NSNotificationCenter defaultCenter] addObserver: self selector:
#selector(hideViews) name: #"Hide" object:nil];
}
This problem arose because this project has only some code for designing.
Sorry if this is a silly question...
You should read up on how notifications work in Cocoa. Consult Apple's documentation for more information: http://developer.apple.com/mac/library/documentation/Cocoa/Reference/Foundation/Classes/NSNotificationCenter_Class/Reference/Reference.html
Basically, NSNotificationCenter is a class that broadcasts NSNotifications from one object to potentially many observing objects. One object can post a notification
[[NSNotificationCenter defaultCenter] postNotificationName:#"NotificationName" object:self];
and other objects can listen for this notification.
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(notificationHandler:) object:theObjectThatPostedTheNotification];
Then, when the first object posts the notification, NSNotificationCenter will notify the other observing object, and notificationHandler: gets called.