Old McStopher
Old McStopher

Reputation: 6359

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?

Upvotes: 0

Views: 2106

Answers (2)

jscs
jscs

Reputation: 64022

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

Upvotes: 0

Jim Puls
Jim Puls

Reputation: 81142

Everything you posted ("Option 1") is okay. See the docs:

removeObserver:

Removes all the entries specifying a given observer from the receiver’s dispatch table.

- (void)removeObserver:(id)notificationObserver

You just need to call removeObserver: once; there's a separate removeObserver:name:object: method if you want to remove just a single observance of a specific notification.

Upvotes: 1

Related Questions