8

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

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

这对我来说没有意义。如果它是非弱引用,那么它不是强引用吗?所以 NSNotificationCenter 仍然是所有者,所以对象不会解除分配(直到手动取消注册),所以在这种情况下说它是“归零”是没有意义的。

如果这是指一种__unsafe_unretained参考,那么问题是……那么 NSNotificationCenter 将如何避免向僵尸发送消息?

4

2 回答 2

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;
}

如您所见,当对象使用自定义-retain-release方法时,不能保证它们完全支持弱引用(另请注意,您可以将完全不同的对象用于对象的弱引用,尽管这是另一个话题) .

objc_destructInstance这是因为弱引用是由, which calls objc_clearDeallocating, which calls清理的weak_clear_no_lock

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

因此,运行时允许您实现方法-allowsWeakReference(and retainWeakReference) 来禁用对对象的弱引用,在这种情况下,它很可能会通过-dealloc在对象上调动而归零。当然,这都是实现细节,所以 NSNotificationCenter 可以有它自己的创新做事方式,但这是我最好的猜测,没有尝试反汇编 NSNotificationCenter。

于 2015-06-11T00:11:58.313 回答
-1

将属性声明为 strong 会使该属性成为强引用。将其声明为弱使用归零弱引用。unsafe_unretained 修饰符使用非归零弱引用

简而言之:non-weak zeroing reference==unsafe_unretained refernce

参考:

https://mikeash.com/pyblog/friday-qa-2011-09-30-automatic-reference-counting.html http://www.jessesquires.com/UIKit-changes-in-iOS-9/

于 2016-07-26T03:35:48.877 回答