问题
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?
回答1:
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.
来源:https://stackoverflow.com/questions/14854635/how-can-the-objective-c-runtime-know-whether-a-weakly-referenced-object-is-still