0

I have an iPad app that uses a proprietary library object which registers for a "UIScreenDidConnectNotification". Occasionally this object is deallocated and reallocated behind the scenes. As it is in a library, I cannot ensure that it is properly removing this observer.

Is there a way for me to manually remove all/any observers for a specific notification (i.e. UIScreenDidConnectNotification) without having any access to the object that has registered. This would keep the application from sending the message to a deallocated object.

Update: Here is the easiest way to fix my problem. I wish I could do a better job, but life is too short. #import #import

@interface NSNotificationCenter (AllObservers)
@end

@implementation NSNotificationCenter (AllObservers)

// This function runs before main to swap in our special version of addObserver
+ (void) load
{
    Method original, swizzled;
    original = class_getInstanceMethod(self, @selector(addObserver:selector:name:object:));
    swizzled = class_getInstanceMethod(self, @selector(swizzled_addObserver:selector:name:object:));

    method_exchangeImplementations(original, swizzled);


// This function runs before main to swap in our special version of addObserver
+ (void) load
{
    Method original, swizzled;
    original = class_getInstanceMethod(self, @selector(addObserver:selector:name:object:));
    swizzled = class_getInstanceMethod(self, @selector(swizzled_addObserver:selector:name:object:));

    method_exchangeImplementations(original, swizzled);
}

/*
    Use this function to remove any unwieldy behavior for adding observers
 */
- (void) swizzled_addObserver:(id)notificationObserver selector:(SEL)notificationSelector name:(NSString *)notificationName object:(id)notificationSender
{
    NSString *notification = [[NSString alloc] initWithUTF8String: "UIScreenDidConnectNotification" ];

    // It's a hack, but I just won't allow my app to add this type of notificiation
    if([notificationName isEqualToString: notification])
    {
        printf("### screen notifcation added for an observer: %s\n", [notificationSender UTF8String] );
    }
    else
    {
        // Calls the original addObserver function
        [self swizzled_addObserver:notificationObserver selector:notificationSelector name:notificationName object:notificationSender];
    }   
}
Gandalf458
  • 2,139
  • 1
  • 21
  • 36

2 Answers2

2

As it is in a library, I cannot ensure that it is properly removing this observer.

If the object is created in a library, it's not your responsibility to remove the object. If the library is deallocating the object without removing it from the notification center, that's a clear bug in the library.

Is there a way for me to manually remove all/any observers for a specific notification... without having any access to the object that has registered.

There's nothing in the API for NSNotificationCenter that lets you do that. Just the opposite, in fact -- the methods that let you remove the observer all require a pointer to a specific object.

Caleb
  • 124,013
  • 19
  • 183
  • 272
  • You're right that there isn't an API method for doing this. I might one day come up with an even better solution than swizzling the addObserver method to not respond to UIScreenDidConnectNotification – Gandalf458 Jul 17 '13 at 23:21
1

I agree with both of Caleb's points: it is not your responsibility to perform this task and there is nothing in the API to support it.

However... if you feel like hacking something in to perform this task for whatever reason, refer to this thread: How to retrieve all NSNotificationCenter observers?

The selected answer of that thread has a category for NSNotificationCenter that allows you to retrieve all observers for a given notification name. Again, this is not recommended though.

Community
  • 1
  • 1
MikeS
  • 3,891
  • 6
  • 35
  • 51
  • That sounds like what I will at least try to do. Thank you! @Caleb I agree that it's the responsibility of the library, and I wish that it wasn't put on my shoulders to take care of their mistake. I can't wait for an update that may never come though. I think that it's our fault the object gets de/reallocated. However, I have been trudging through the code for nearly a week trying to figure out where this atrocity is happening. – Gandalf458 Jul 17 '13 at 21:36
  • Just make sure you don't accidentally remove observers you did not intend to remove, as I'm sure that could create all sorts of strange bugs that would be lots of fun to track down :) – MikeS Jul 17 '13 at 21:38
  • That is my biggest concern. What I'm hoping is that I can use this to somehow track down that specific object and only remove it's observer. I have some fun hours the rest of today at work. If I get it working any better, I will try to post the code for reference. – Gandalf458 Jul 17 '13 at 21:56