Objective-C运行时如何知道弱引用对象是否仍然存活?

Lui*_*BOL 2 weak-references objective-c objective-c-runtime automatic-ref-counting

随着ARC的出现,一些新功能可供开发人员使用弱引用对象.id objc_loadWeak(id *location)是其中之一.此函数接收一个参数,该参数对应于存储弱对象的内存中的某个位置,如果该对象仍处于活动状态或nil已取消分配,则返回该对象.

似乎当一个对象obj被存储weak在一个位置locationid objc_storeWeak(id *location, id obj),obj被放在一个"弱地图"中,location作为一个键.但是,为了检索obj,objc_loadWeak不仅可以location用作键并返回值,这对应于obj.它还必须检查是否obj仍然存活,nil如果不再存在则返回.

但是,objc_loadWeak无法尝试读取对象的保留计数,因为该对象可能已被释放.此外,尽管弱地图,objc_storeWeak,objc_loadWeakNSObject类以相同的文件(实施NSObject.mm)NSObjectdealloc方法没有信号给正被释放的对象消失弱地图.

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

小智 9

NSObject的dealloc方法不向弱映射发信号通知正被解除分配的对象正在消失.

确实如此.

- [NSObject dealloc]
Run Code Online (Sandbox Code Playgroud)

电话

_objc_rootDealloc(self);
Run Code Online (Sandbox Code Playgroud)

反过来调用

object_dispose()
Run Code Online (Sandbox Code Playgroud)

反过来打电话

objc_destructInstance()
Run Code Online (Sandbox Code Playgroud)

最后打电话给

objc_clear_deallocating()
Run Code Online (Sandbox Code Playgroud)

最后一个函数如下所示:

    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);
}
Run Code Online (Sandbox Code Playgroud)

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