2

随着 ARC 的出现,提供了一些新功能,允许开发人员使用弱引用对象。id objc_loadWeak(id *location)是其中之一。此函数接收一个参数,该参数与内存中存储弱对象的位置相对应,如果该对象仍然存在或nil已被释放,则返回该对象。

似乎当一个对象obj存储weak在一个带有 的位置locationid objc_storeWeak(id *location, id obj)obj它被放在一个“弱地图”中,location作为一个键。但是,为了检索objobjc_loadWeak不能只location用作键并返回对应的值obj。它还必须检查是否还活着,如果不再obj存在则返回。nil

但是,objc_loadWeak不能尝试读取对象的保留计数,因为对象可能已被释放。此外,尽管弱映射、objc_storeWeakobjc_loadWeakNSObject是在同一个文件(NSObject.mm)中实现的,但NSObjectdealloc方法不会向弱映射发出信号,表明正在被释放的对象正在消失。

那么,Objective-C 运行时如何判断一个weak对象是否还活着呢?

4

1 回答 1

9

NSObject 的 dealloc 方法不会向弱映射发出信号,表明正在被释放的对象正在消失。

确实如此。

- [NSObject dealloc]

来电

_objc_rootDealloc(self);

这反过来又调用

object_dispose()

这反过来又调用

objc_destructInstance()

最终调用

objc_clear_deallocating()

最后一个函数如下所示:

    void 
objc_clear_deallocating(id obj) 
{
    assert(obj);
    assert(!UseGC);

    SideTable *table = SideTable::tableForPointer(obj); /* *** THIS LINE *** */

    // clear any weak table items
    // clear extra retain count and deallocating bit
    // (fixme warn or abort if extra retain count == 0 ?)
    OSSpinLockLock(&table->slock);
    if (seen_weak_refs) {
    arr_clear_deallocating(&table->weak_table, obj); /* *** THIS LINE *** */
    }
    table->refcnts.erase(DISGUISE(obj)); /* *** THIS LINE *** */
    OSSpinLockUnlock(&table->slock);
}

突出显示的三行具有魔力。SideTable是一个实现的 C++ 类NSObject.mm,其中refcnts成员变量的作用与听起来完全一样:它保存引用计数。

于 2013-02-13T13:44:20.853 回答