Search code examples
objective-ccocoansnotificationsnsnotificationcenter

NSNotificationCenter - Observing for Notification Name with Multiple Methods


So, I have an object that has methods to toggle watching for a certain notification name, like so:

- (void)startWatchingForA
{
    [[NSNotificationCenter defaultCenter] addObserver: self
                                             selector: @selector(handleA:)
                                                 name: SomeNotificationName
                                               object: nil];
}

- (void)stopWatchingForA
{
    [[NSNotificationCenter defaultCenter] removeObserver: self
                                                    name: SomeNotificationName
                                                  object: nil];
}

Which works fine. However, I have another method, handleB:, that needs to respond to the same notification.

- (void)startWatchingForB
{
    [[NSNotificationCenter defaultCenter] addObserver: self
                                             selector: @selector(handleB:)
                                                 name: SomeNotificationName
                                               object: nil];
}

- (void)stopWatchingForB
{
    [[NSNotificationCenter defaultCenter] removeObserver: self
                                                    name: SomeNotificationName
                                                  object: nil];
}

The issue is that, should stopWatchingA or stopWatchingB be called, the object will stop watching for both. Is there some way to remove one observation instance, but not the other?

Ideally, when I call stopWatchingForA, I want handleA: to not be called, entirely independent of B.


Solution

  • How about a slight redesign? Only one method to receive the notification, and two flags to indicate what you want to do with it.

    @implementation ThisObject
    {
       BOOL isWatchingForA;
       BOOL isWatchingForB;
    }
    
    - (void) registerForNotifications {
    
        [[NSNotificationCenter defaultCenter] addObserver: self
                                             selector: @selector(handleNotification:)
                                                 name: SomeNotificationName
                                               object: nil];
    }
    
    - (void) deregisterForNotifications {
        if( !isWatchingA && !isWatchingB ){
            [[NSNotificationCenter defaultCenter] removeObserver: self
                                                    name: SomeNotificationName
                                                  object: nil];
        }
    }
    
    
    - (void) startWatchingForA {
        isWatchingForA = YES;
    }
    - (void) stopWatchingForA {
        isWatchingForA = NO;
    }
    
    - (void) startWatchingForB {
        isWatchingForB = YES;
    }
    - (void) stopWatchingForB {
        isWatchingForB = NO;
    }
    
    - (void) handleNotification: (NSNotification *)note {
    
        if( isWatchingForA ){
            [self handleA:note];
        }
        if( isWatchingB ){
            [self handleB:note];
        }
    }
    
    //...
    
    @end