什么是"非弱归零参考"

nat*_*evw 7 cocoa memory-management objective-c nsnotificationcenter osx-elcapitan

OS X v10.11 beta发行说明中,我发现以下内容:

NSNotificationCenter和NSDistributedNotificationCenter不再向可能已解除分配的已注册观察者发送通知.如果观察者能够存储为归零弱引用,则底层存储将观察者存储为归零弱引用.或者,如果对象不能被弱存储(因为它具有会阻止运行时能够弱存储对象的自定义保留/释放机制),则该对象被存储为非弱的归零引用.这意味着观察者不需要在他们的释放方法中取消注册.[强调我的]

这对我来说没有意义.如果它是一个非弱参考,那么它不是一个强大的参考吗?因此,NSNotificationCenter仍然是所有者,因此该对象不会解除分配(直到手动取消注册),因此在此上下文中说它是"归零"是没有意义的.

如果这是指某种__unsafe_unretained参考,那么问题是......那么NSNotificationCenter如何避免传播僵尸?

Ric*_*III 4

这个问题的答案深藏在 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;
}
Run Code Online (Sandbox Code Playgroud)

正如您所看到的,当对象使用自定义-retain-release方法时,并不能保证它们完全支持弱引用(另请注意,您可以为对象的弱引用使用完全不同的对象,尽管这是另一个主题) 。

这是因为弱引用被objc_destructInstance, which 调用objc_clearDeallocating, which 调用清除weak_clear_no_lock

现在,objc_destructInstance不需要由自定义对象实现调用,尽管大多数对象都会调用它。

因此,运行时允许您实现方法-allowsWeakReference( 和retainWeakReference) 来禁用对对象的弱引用,在这种情况下,它很可能通过调整-dealloc对象来清零。当然,这都是实现细节,因此 NSNotificationCenter 可以有自己的创新方式来做事,但这是我最好的猜测,而无需尝试分解 NSNotificationCenter。