How to stop the Observer in NSNotification to called twice?

IphoneObjective CIosNsnotifications

Iphone Problem Overview


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];
}

Iphone Solutions


Solution 1 - Iphone

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 - Iphone

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 - Iphone

Try to removeObserver in viewWillDisappear method :

-(void)viewWillDisappear:(BOOL)animated{

[[NSNotificationCenter defaultCenter] removeObserver:self name:@"startAnimating" object:nil]; }

Solution 4 - Iphone

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 - Iphone

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.

Solution 6 - Iphone

I had two instances of the same class and it took me some time before I have realised that the notification is not running twice in one instance of that class but twice in two instances.

Solution 7 - Iphone

I use notifications in a document-based app. Every document's observer class (a ViewController) caught the notification. Two documents open, function was called twice. Three documents open... you get the drift.

To limit who receives the notification, you can specify that you're interested in a particular object, but this has a twist: the object needs to be the same instance of a class object; you cannot simply compare a value; so UUID does not get matched, but an instance of

class DocumentID {
    var id = UUID()
}

works fine. Inject this from your Document to every class that sends or receives notifications, and you've limited notifications to your document.

Solution 8 - Iphone

Swift 5+ Solution

NotificationCenter.default.removeObserver(self, name: aName, object: nil)
NotificationCenter.default.addObserver(self, selector: #selector(aSelector), name: aName, object: nil)

A couple of tips (and a couple ALWAYS means 2):

  1. Selector method must be exposed to @objc to work, so per our example:

    @objc func aSelector() { //do work here }
    
  1. I put the notifications in the init() and deinit() and use singletons to avoid repeating them, like this:

    init() {
        NotificationCenter.default.addObserver(self, selector: #selector(aSelector), name: aName, object: nil)
        //add any other notifications here
    }
    
    deinit() {
        NotificationCenter.default.removeObserver(self)
    }
    

Solution 9 - Iphone

In my case Notification is calling the number of time i'm appearing in same screen and which is caused to triggered same action X numberofTime i'm entered to screen. So I've removed Notification observer in viewWillDisappear which is actually worked and stopped the multiple time triggered action/methods in same screen.

Thanks to Himanth's answer i've figured it out

  • Swift4 > addObserver
 override func viewDidLoad(){
       super.viewDidLoad()

      NotificationCenter.default.addObserver(self, selector: #selector(self.yourNotificationAction(notification:)), name: Notification.Name("yourNotificationName"), object: nil)

}

>removeObserver when screen is disappear

 override func viewWillDisappear(_ animated: Bool) {
        super.viewWillDisappear(animated)
        
        NotificationCenter.default.removeObserver(self, name: Notification.Name("yourNotificationName"), object: nil)
      
    }

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionAzharView Question on Stackoverflow
Solution 1 - IphoneEmptyStackView Answer on Stackoverflow
Solution 2 - Iphonetfrank377View Answer on Stackoverflow
Solution 3 - IphonebhadreshView Answer on Stackoverflow
Solution 4 - IphonestcuiView Answer on Stackoverflow
Solution 5 - IphoneJoysonView Answer on Stackoverflow
Solution 6 - IphoneVladimír SlavíkView Answer on Stackoverflow
Solution 7 - Iphonegreen_knightView Answer on Stackoverflow
Solution 8 - IphoneMichaelView Answer on Stackoverflow
Solution 9 - IphonesteveSarsawaView Answer on Stackoverflow