Objective-C运行时如何知道弱引用的对象是否仍然存在? [英] How can the Objective-C runtime know whether a weakly referenced object is still alive?

查看:95
本文介绍了Objective-C运行时如何知道弱引用的对象是否仍然存在?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

似乎当将对象obj作为weak存储在具有id objc_storeWeak(id *location, id obj)的位置location中时,将obj置于弱映射"中,并以location作为键.但是,为了检索objobjc_loadWeak不仅可以使用location作为键并返回对应于obj的值.它还必须检查obj是否仍然有效,以返回nil(如果不再存在).

但是,objc_loadWeak无法尝试读取对象的保留计数,因为该对象可能已被释放.此外,尽管弱映射objc_storeWeakobjc_loadWeakNSObject类在同一文件中实现(解决方案

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是在NSObject.mm中实现的C ++类,其中的refcnts成员变量完全像听起来那样:它保存引用计数.

With the advent of ARC, some new functions were made available to allow developers to play around with weakly referenced objects. id objc_loadWeak(id *location) is one of them. This function receives one parameter correspoding to a location in memory where a weak object was stored and returns this object if it is still alive or nil if it were deallocated.

It seems that when an object obj is stored as weak in a location location with id objc_storeWeak(id *location, id obj), obj is put in a "weak map", with location as a key. However, in order to retrieve obj, objc_loadWeak can not only use location as a key and return the value, which corresponds to obj. It must also check whether obj is still alive to return nil if it is not anymore.

However, objc_loadWeak can not try to read the object's retain count, because the object may have been deallocated. Moreover, although the weak map, objc_storeWeak, objc_loadWeak and the NSObject class are implemented in the same file (NSObject.mm), NSObject's dealloc method doesn't signals to the weak map that the object that is being deallocated is going away.

So, how does the Objective-C runtime figure out whether a weak object is still alive?

解决方案

NSObject's dealloc method doesn't signals to the weak map that the object that is being deallocated is going away.

It does.

- [NSObject dealloc]

calls

_objc_rootDealloc(self);

which in turn invokes

object_dispose()

which in turn calls

objc_destructInstance()

which finally calls

objc_clear_deallocating()

This last function looks like this:

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

The three highlighted lines do the magic. SideTable is a C++ class implemented in NSObject.mm of which the refcnts member variable does exactly what it sounds like it does: it holds reference counts.

这篇关于Objective-C运行时如何知道弱引用的对象是否仍然存在?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆