How to stop the Observer in NSNotification to called twice?
Solution 1
Solution 1: The first thing is to check if the notification itself is posted twice.
Solution 2: Even if the notification is posted only once, the action will be called as many times you've added the observer for the notification (no matter the notification is same or not). For example, the following two lines will register the observer(self
) for the same notification(aSelector
) twice.
[[NSNotificationCenter defaultCenter] addObserver:self selector:aSelector name:aName object:nil];
[[NSNotificationCenter defaultCenter] addObserver:self selector:aSelector name:aName object:nil];
You have to find where you are adding observer for the second time, and remove it. And also make sure that the code where you are add the observer is not called twice.
Solution 3: If you are not sure whether you have already added the observer or not, you can simply do the following. This will make sure that the observer is added only once.
[[NSNotificationCenter defaultCenter] removeObserver:self name:aName object:nil];
[[NSNotificationCenter defaultCenter] addObserver:self selector:aSelector name:aName object:nil];
Solution 2
If your addObserver
method is run multiple times, it will create multiple observers. My issue was that I somehow placed my observer in viewWillAppear
which appeared multiple times before I posted the notification and it resulted in my observer being called multiple times.
While EmptyStack's 3rd solution works, there is a reason your observer is being called twice, so by finding it, you can prevent needless lines of code instead of removing and adding the same observer.
I would suggest putting your observer in viewDidLoad
to avoid simple errors like the one I experienced.
Solution 3
Try to removeObserver in viewWillDisappear method :
-(void)viewWillDisappear:(BOOL)animated{
[[NSNotificationCenter defaultCenter] removeObserver:self name:@"startAnimating" object:nil]; }
Solution 4
Try set a breakpoint on [[NSNotificationCenter defaultCenter] addObserver:self selector:aSelector name:aName object:nil];
and check if it is called more than once.
Solution 5
For those looking for a solution in Swift 2.2 and above and who have reached this question like me you can create an extension as follows :
import Foundation
extension NSNotificationCenter {
func setObserver(observer: AnyObject, selector: Selector, name: String?, object: AnyObject?) {
NSNotificationCenter.defaultCenter().removeObserver(observer, name: name, object: object)
NSNotificationCenter.defaultCenter().addObserver(observer, selector: selector, name: name, object: object)
}
}
You can call this method as follows :
NSNotificationCenter.defaultCenter().setObserver(self, selector: #selector(methodName), name: "name", object: nil)
The extension will handle the removal of previous observer if it exists. Even if there was no previous observer present this code won't crash.
Azhar
.net / iOS / Android / Windows Mobile/ React-native Optimization Optimization Optimization
Updated on July 08, 2022Comments
-
Azhar almost 2 years
I have an observer of
NSNotification
which is called twice. I do not know what to do with it.I googled it but no solution found.
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(connectedToServer:) name:@"ConnectedToServer" object:nil]; - (void)connectedToServer:(NSNotification*)notification { [[NSNotificationCenter defaultCenter] postNotificationName:@"SendMessageToServer" object:message]; }
-
brigadir over 12 yearsMaybe you receive the notification two times. To check it set breakpoint in
aSelector
and look at calling stack. -
SamehDos over 12 years[[NSNotificationCenter defaultCenter] removeObserver:self name:aName object:nil]; is the best answer
-
toblerpwn over 11 yearsAs with Azhar, I could not resolve this issue using the methods above. Not sure what was going on - but in my case I switched to using a
delegate
for my callback needs. This is not a solution for all cases, but a workaround that may help some future readers who are also stuck. -
RyanG about 11 yearsWow I was debugging this for way too long... I was calling addObserver at the beginning of a function and not removing it correctly.. hence my function being called multiple times. Added the remove above it and works perfect.
-
Ashwin G about 10 yearsThis is probably the solution. A breakpoint can be kept in the addObserver method to check how many times this same observer has been added.
-
H.Rabiee over 9 yearsif you're registering the observer in one of your nib init methods then it's most likely being called (and registered) more than once.
-
Maverick1st about 9 yearsIf i read this a few hours before i would have saved sooo much time. just couldn't figure out, why multiple observers where registered. Now moved the registration from viewWillAppear to viewDidLoad and it works like a charm. Thx a lot.
-
Bhavin Ramani over 8 yearsI got solution from solution 3. I have implement this method [NSNotificationCenter defaultCenter] in view did load and view did load was called two times in class.
-
olha almost 8 yearsSolution 2 rocks, because I add notification once in
awakeFromNib
, andawakeFromNib
is called twice. -
ToolmakerSteve almost 8 years
addObserver
inviewWillAppear
works fine, if you add the correspondingremoveObserver
inviewWillDisappear
, as suggested by bhadresh! (Which you should do anyway - no reason to have unnecessary observers hanging around.) If you putaddObserver
inviewDidLoad
, then where do you putremoveObserver
? Do you really want the observer hanging around after your view is not being seen? -
RamaKrishna Chunduri almost 8 yearsuse GCD and dispatch once to ensure observer is added only once. static dispatch_once_t onceToken; dispatch_once(&onceToken, ^{ //add observer code });
-
Cian over 7 yearsUsing this way, if the self(i.e. a UIViewcontroller) is allocated again and again, every new object of self would create an observer. Using above code would only remove the current self's observer but not the old self's observer. Have faced this issue before.
-
Jonny about 7 yearsIn my case viewDidLoad was called twice, unexpectedly. Do not rely on viewDidLoad being called only once. I mean I do, but this was the culprit this time.
-
OxyFlax over 6 years@Jonny How did you solve the problem? That's my case, viewDidLoad, ViewWillAppear are called twice and at the same time so delete the notification before adding it doesn't solve the problem...
-
Jonny over 6 years@OxyFlax I don't remember what I was working on. But normally doing addObserver using NotificationCenter in viewDidLoad should be correct... For NC I no longer use removeObserver at all, since iOS 9 - see the docs under discussion: developer.apple.com/documentation/foundation/…
-
bruce1337 over 6 yearsJust to note that there are many answers elsewhere for questions like "Why was viewDidLoad() called twice?" – and they all emphasize that there is no guarantee that viewDidLoad will only be called once. It would seem that performing removeObserver before addObserver is the way to go.
-
Jack about 6 years@Azhar have you found any solution ?
-
Paul Bruneau over 2 yearsI also had viewdidLoad getting called repeatedly, occasionally. Makes sense. I put the addobserver call in init. If you can't do that, you can wrap it in a dispatch_once as suggested above