大多數與生命週期有關的方法咱們都已經講完了,接下來來看最後一個方法,dealloc。app
dealloc 方法的實現以下:ide
// Replaced by NSZombies
- (void)dealloc {
_objc_rootDealloc(self);
}
void
_objc_rootDealloc(id obj)
{
assert(obj);
obj->rootDealloc();
}
inline void
objc_object::rootDealloc()
{
if (isTaggedPointer()) return; // fixme necessary?
if (fastpath(isa.nonpointer &&
!isa.weakly_referenced &&
!isa.has_assoc &&
!isa.has_cxx_dtor &&
!isa.has_sidetable_rc))
{ // 若是 isa 不是經過指針實現的,不是弱引用,沒有關聯對象,沒有 C++ 析構函數,沒有在 sidetable 中存儲引用計數,直接 free
assert(!sidetable_present());
free(this);
}
else {
object_dispose((id)this);
}
}
複製代碼
object_dispose 的實現以下所示:函數
/*********************************************************************** * object_dispose * fixme * Locking: none **********************************************************************/
id object_dispose(id obj) {
if (!obj) return nil;
objc_destructInstance(obj);
free(obj);
return nil;
}
/*********************************************************************** * objc_destructInstance * Destroys an instance without freeing memory. * Calls C++ destructors. * Calls ARC ivar cleanup. * Removes associative references. * Returns `obj`. Does nothing if `obj` is nil. **********************************************************************/
void *objc_destructInstance(id obj) {
if (obj) {
// Read all of the flags at once for performance.
bool cxx = obj->hasCxxDtor(); // 獲取是否有 C++ 析構函數
bool assoc = obj->hasAssociatedObjects(); // 獲取是否有關聯對象
// This order is important.
if (cxx) object_cxxDestruct(obj); // 若是有析構函數,調用 object_cxxDestruct
if (assoc) _object_remove_assocations(obj); // 若是有關聯對象,調用 _object_remove_assocations
obj->clearDeallocating();
}
return obj;
}
複製代碼
hasCxxDtor 實現以下:ui
inline bool
objc_object::hasCxxDtor()
{
assert(!isTaggedPointer());
if (isa.nonpointer) return isa.has_cxx_dtor;
else return isa.cls->hasCxxDtor();
}
複製代碼
object_cxxDestruct 實現以下:this
/*********************************************************************** * object_cxxDestruct. * Call C++ destructors on obj, if any. * Uses methodListLock and cacheUpdateLock. The caller must hold neither. **********************************************************************/
void object_cxxDestruct(id obj) {
if (!obj) return;
if (obj->isTaggedPointer()) return;
object_cxxDestructFromClass(obj, obj->ISA());
}
/*********************************************************************** * object_cxxDestructFromClass. * Call C++ destructors on obj, starting with cls's * dtor method (if any) followed by superclasses' dtors (if any), * stopping at cls's dtor (if any). * Uses methodListLock and cacheUpdateLock. The caller must hold neither. **********************************************************************/
static void object_cxxDestructFromClass(id obj, Class cls) {
void (*dtor)(id);
// Call cls's dtor first, then superclasses's dtors.
for ( ; cls; cls = cls->superclass) { // 遞歸調用 obj 及其父類的析構函數
if (!cls->hasCxxDtor()) return;
dtor = (void(*)(id))
lookupMethodInClassAndLoadCache(cls, SEL_cxx_destruct); // 查找方法
if (dtor != (void(*)(id))_objc_msgForward_impcache) {
if (PrintCxxCtors) {
_objc_inform("CXX: calling C++ destructors for class %s",
cls->nameForLogging());
}
(*dtor)(obj);
}
}
}
複製代碼
hasAssociatedObjects 實現以下:spa
inline bool
objc_object::hasAssociatedObjects()
{
if (isTaggedPointer()) return true;
if (isa.nonpointer) return isa.has_assoc;
return true;
}
複製代碼
_object_remove_assocations 實現以下,簡而言之就是查找對象關聯的全部對象,並依次調用 ReleaseValue。指針
void _object_remove_assocations(id object) {
vector< ObjcAssociation,ObjcAllocator<ObjcAssociation> > elements;
{
AssociationsManager manager;
AssociationsHashMap &associations(manager.associations());
if (associations.size() == 0) return;
disguised_ptr_t disguised_object = DISGUISE(object);
AssociationsHashMap::iterator i = associations.find(disguised_object);
if (i != associations.end()) {
// copy all of the associations that need to be removed.
ObjectAssociationMap *refs = i->second;
for (ObjectAssociationMap::iterator j = refs->begin(), end = refs->end(); j != end; ++j) {
elements.push_back(j->second);
}
// remove the secondary table.
delete refs;
associations.erase(i);
}
}
// the calls to releaseValue() happen outside of the lock.
for_each(elements.begin(), elements.end(), ReleaseValue());
}
struct ReleaseValue {
void operator() (ObjcAssociation &association) {
releaseValue(association.value(), association.policy());
}
};
複製代碼
clearDeallocating 方法的實現以下:code
inline void
objc_object::clearDeallocating()
{
if (slowpath(!isa.nonpointer)) {
// Slow path for raw pointer isa.
sidetable_clearDeallocating();
}
else if (slowpath(isa.weakly_referenced || isa.has_sidetable_rc)) {
// Slow path for non-pointer isa with weak refs and/or side table data.
clearDeallocating_slow();
}
assert(!sidetable_present());
}
複製代碼
sidetable_clearDeallocating 方法會在 isa 是指針的實現中被調用,其實現以下:orm
void
objc_object::sidetable_clearDeallocating()
{
SideTable& table = SideTables()[this];
// clear any weak table items
// clear extra retain count and deallocating bit
// (fixme warn or abort if extra retain count == 0 ?)
table.lock();
RefcountMap::iterator it = table.refcnts.find(this);
if (it != table.refcnts.end()) {
if (it->second & SIDE_TABLE_WEAKLY_REFERENCED) {
weak_clear_no_lock(&table.weak_table, (id)this);
}
table.refcnts.erase(it);
}
table.unlock();
}
複製代碼
clearDeallocating_slow 方法會在 isa 是非指針的實現中被調用,其實現以下:對象
// Slow path of clearDeallocating()
// for objects with nonpointer isa
// that were ever weakly referenced
// or whose retain count ever overflowed to the side table.
NEVER_INLINE void
objc_object::clearDeallocating_slow()
{
assert(isa.nonpointer && (isa.weakly_referenced || isa.has_sidetable_rc));
SideTable& table = SideTables()[this];
table.lock();
if (isa.weakly_referenced) {
weak_clear_no_lock(&table.weak_table, (id)this);
}
if (isa.has_sidetable_rc) {
table.refcnts.erase(this);
}
table.unlock();
}
複製代碼