这个问题的答案深藏在 Objective-C 运行时,以及__weak
变量的实际工作方式。为了解释,让我们看一下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;
}
如您所见,当对象使用自定义-retain
和-release
方法时,不能保证它们完全支持弱引用(另请注意,您可以将完全不同的对象用于对象的弱引用,尽管这是另一个话题) .
objc_destructInstance
这是因为弱引用是由, which calls objc_clearDeallocating
, which calls清理的weak_clear_no_lock
。
现在,objc_destructInstance
自定义对象实现不需要调用它,尽管大多数对象都会调用它。
因此,运行时允许您实现方法-allowsWeakReference
(and retainWeakReference
) 来禁用对对象的弱引用,在这种情况下,它很可能会通过-dealloc
在对象上调动而归零。当然,这都是实现细节,所以 NSNotificationCenter 可以有它自己的创新做事方式,但这是我最好的猜测,没有尝试反汇编 NSNotificationCenter。