The answer lies deeply in the objective-c runtime and how __weak variables really work. To explain, take a look at objc_weak.mm :
id weak_read_no_lock(weak_table_t *weak_table, id *referrer_id) { ... if (! referent->ISA()->hasCustomRR()) { if (! referent->rootTryRetain()) { return nil; } } else { BOOL (*tryRetain)(objc_object *, SEL) = (BOOL(*)(objc_object *, SEL)) object_getMethodImplementation((id)referent, SEL_retainWeakReference); if ((IMP)tryRetain == _objc_msgForward) { return nil; } if (! (*tryRetain)(referent, SEL_retainWeakReference)) { return nil; } } return (id)referent; }
As you can see, when the user -retain and -release user methods are used by the object, it does not guarantee that they support weak links at all (also note that you can use a completely different object for weak links of the object, although this is a topic at a different time) .
This is because weak links are cleared using objc_destructInstance , which calls objc_clearDeallocating , which calls weak_clear_no_lock .
Now objc_destructInstance NOT required to call custom object implementations, although most objects will call it.
Thus, the runtime allows you to implement the -allowsWeakReference (and retainWeakReference ) method to disable weak references to your object, in which case it is most likely to be nullified using the swizzling -dealloc object. Of course, these are all implementation details, so the NSNotificationCenter may have its own innovative way of doing something, but this is my best guess without trying to make out the NSNotificationCenter.
source share