Lings
Lings

Reputation: 124

How does the NSNotificationCenter detect the deallocated observer in ARC?

I found that when using NSNotificationCenter in ARC, even you forget to remove the observer from defaultCenter, and the observer has deallocated, then you post the notification that the observer observed , there is no crash anymore !!

before Xcode 4, there is no ARC, we must remove the observer from default notification center in dealloc function, like this:

- (void)dealloc {
    [[NSNotificationCenter defaultCenter] removeObserver:self];
}

otherwise when a binded notification posted, it will triger a crash !

so, the question is how does the NSNotificationCenter detect the deallocated observer in ARC ?

Upvotes: 0

Views: 2195

Answers (1)

Martin R
Martin R

Reputation: 539775

Update: As of iOS 9 and OS X 10.11, it is no longer necessary for an NSNotificationCenter observer to un-register itself when being deallocated. (Source: Unregistering NSNotificationCenter Observers in iOS 9)


(Old answer:) Even with ARC, you have to remove an observer from the notification center when it is deallocated. It may be pure chance that your program did not crash.

The following program demonstrates this. I have activated the "Enable Zombie Objects" option.

@interface MyObject : NSObject
@end

@implementation  MyObject

-(id)init
{
    self = [super init];
    if (self) {
        [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(notify:) name:@"test" object:nil];
    }
    return self;
}
- (void)dealloc
{
    NSLog(@"dealloc");
    //[[NSNotificationCenter defaultCenter] removeObserver:self];
}
- (void)notify:(NSNotification *)notification
{
    NSLog(@"notify");
}

@end

int main(int argc, const char * argv[])
{
    @autoreleasepool {
        MyObject *o = [[MyObject alloc] init];
        [[NSNotificationCenter defaultCenter] postNotificationName:@"test" object:nil];
        o = nil; // This causes the object to be deallocated
        // ... and this will crash
        [[NSNotificationCenter defaultCenter] postNotificationName:@"test" object:nil];
    }
    return 0;
}

Output:

notifytest[593:303] notify
notifytest[593:303] dealloc
notifytest[593:303] *** -[MyObject notify:]: message sent to deallocated instance 0x100114290

Upvotes: 6

Related Questions