Search code examples
iphoneobjective-ccocoa-touchnsnotificationsnsnotificationcenter

Add another selector/name pair to an existing observer in NSNotificationCenter


I'm not sure the exact reason for it (other than the ambiguity described below), but I've read that multiple observers shouldn't be added to the NSNotificationCenter for the same object. However, I would like to add a second selector/name pair to the same object in the notification center.

I added the first one as follows:

[[NSNotificationCenter defaultCenter] addObserver:self
                                         selector:@selector(method1:) 
                                             name:@"method1Notification"
                                           object:nil];

Option 1:

To add the second (like below) would seem to add "self" to the notification center again.

[[NSNotificationCenter defaultCenter] addObserver:self
                                         selector:@selector(method2:) 
                                             name:@"method2Notification"
                                           object:nil];

Is this okay? Or, if necessary, is there a way to simply add another selector/name pair to the "self" entry in the default notification center?


Option 2: (Pseudocode)

[[[NSNotificationCenter defaultCenter] mySelfObserver]
                        addSelector:@selector(method2:) 
                               name:@"method2Notification"
                             object:nil];

Ambiguity:

It would seem that either way, if it were added a second time, in dealloc: it might need to be removed as an observer twice?

[[NSNotificationCenter defaultCenter] removeObserver:self];
// ... REMOVE IT AGAIN IF OBSERVER ADDED TWICE TO NOTIFICATION CENTER?

Solution

  • I think you're a little confused. It's perfectly fine to add a given observer any number of times, as long as the notifications or objects are different.

    If you add an observer multiple times for a single notification/object combo, you will receive multiple notifications -- your notification method will be called once for each time you added the observer. This is usually not desirable, and I think that's the recommendation that you've seen.

    You also only need to call removeObserver: once for any observer, no matter how many things it's observing.

    - (void)registerForNotifications
    {
        NSNotificationCenter * noteCenter = [NSNotificationCenter defaultCenter];
        [noteCenter addObserver:self
                       selector:@selector(keyboardWasShown:)
                           name:UIKeyboardDidShowNotification 
                         object:nil];
    
        [noteCenter addObserver:self
                       selector:@selector(keyboardWillBeHidden:)
                           name:UIKeyboardWillHideNotification 
                         object:nil];
        // Totally fine up to this point; this object is observing two different
        // notifications.
        // Now, add two different observations for the same notification, but
        // with _different_ objects:
        [noteCenter addObserver:self
                       selector:@selector(fluffyHasReproduced:)
                           name:RabbitsHaveReproducedNotification
                         object:MyRabbitFluffy];
        [noteCenter addObserver:self
                       selector:@selector(luckyHasReproduced:)
                           name:RabbitsHaveReproducedNotification
                         object:MyRabbitLucky];
        // This is fine; the appropriate rabbit notification method will only be
        // called when the corresponding rabbit reproduces.
        // However...
        // This will make luckyHasReproduced: be called _twice_ whenever
        // MyRabbitLucky posts RabbitsHaveReproducedNotification
        [noteCenter addObserver:self
                       selector:@selector(luckyHasReproduced:)
                           name:RabbitsHaveReproducedNotification
                         object:MyRabbitLucky];
        // Further,
        // this is probably not what you want. otherRabbitsHaveReproduced: is
        // going to be called whenever either Fluffy or Lucky post their
        // notifications, too. The nil object acts as a wildcard.
        [noteCenter addObserver:self
                       selector:@selector(otherRabbitsHaveReproduced:) 
                           name:RabbitsHaveReproducedNotification 
                         object:nil];
    
    }
    

    Later, when appropriate (viewWillDisappear:, or viewDidUnload: for view controllers, depending on the nature of the notifications; dealloc for other objects):

    - (void) unregisterForNotifications {
        // Clear out _all_ observations that this object was making
        [[NSNotificationCenter defaultCenter] removeObserver:self];
    }