Как среда выполнения Objective C может узнать, жив ли объект со слабой ссылкой?

С появлением ARC стали доступны некоторые новые функции, позволяющие разработчикам поиграться со объектами со слабыми ссылками. id objc_loadWeak(id *location) это один из них. Эта функция получает соответствующий параметр в определенном месте в памяти, где хранился слабый объект, и возвращает этот объект, если он еще жив или nil если бы это было освобождено.

Кажется, что когда объект obj хранится как weak в месте location с id objc_storeWeak(id *location, id obj), obj помещается в "слабую карту", ​​с location в качестве ключа. Однако для того, чтобы получить obj, objc_loadWeak можно не только использовать location в качестве ключа и вернуть значение, которое соответствует obj, Он также должен проверить, obj еще жив, чтобы вернуться nil если это больше не так.

Тем не мение, objc_loadWeak не может попытаться прочитать счет удержания объекта, потому что объект, возможно, был освобожден. Более того, хотя слабая карта, objc_storeWeak, objc_loadWeak и NSObject класс реализован в одном файле ( NSObject.mm), NSObject"s dealloc Метод не сообщает слабой карте, что объект, который освобождается, исчезает.

Итак, как во время выполнения Objective-C выяснить, является ли weak объект еще жив?

1 ответ

Решение

Метод dealloc NSObject не сообщает слабой карте, что объект, который был освобожден, исчезает.

Оно делает.

- [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 Переменная-член делает именно то, что звучит, как и она: она содержит количество ссылок.

Другие вопросы по тегам