Objc对象的销毁过程

销毁的源头

调用-release,release会调用:
uintptr_t objc_object::sidetable_release(bool performDealloc)

sidetable_release():

以下是runtime源码 NSObject.mm 1584行

bjc_object::sidetable_release(bool performDealloc)
{
#if SUPPORT_NONPOINTER_ISA
    assert(!isa.nonpointer);
#endif
    SideTable& table = SideTables()[this];

    bool do_dealloc = false;
    //加锁
    table.lock();
//获取当前对象所在的sidetable(一个hash表),在sidetable.refcnts(RefcountMap,一个map)中查到当前对象的迭代器
    RefcountMap::iterator it = table.refcnts.find(this);
    //接着判断迭代器是否是指向了sidetable的end
    //如果是就代表找不到:
    if (it == table.refcnts.end()) {
      //将对象标记为“正在析构”
      //标记需要dealloc
        do_dealloc = true;
        table.refcnts[this] = SIDE_TABLE_DEALLOCATING;
    } else if (it->second < SIDE_TABLE_DEALLOCATING) {
      //判断之前存储的引用计数值是否为 0,避免负数
      //将对象标记为“正在析构”
      //标记需要dealloc
        // SIDE_TABLE_WEAKLY_REFERENCED may be set. Don't change it.
        do_dealloc = true;
        it->second |= SIDE_TABLE_DEALLOCATING;
    } else if (! (it->second & SIDE_TABLE_RC_PINNED)) {
       //将引用计数减一
        it->second -= SIDE_TABLE_RC_ONE;
    }
   //解锁
    table.unlock();
    if (do_dealloc  &&  performDealloc) {
    //调用对象的dealloc方法:
        ((void(*)(objc_object *, SEL))objc_msgSend)(this, SEL_dealloc);
    }
    return do_dealloc;
}

如果调用了dealloc:

进行以下过程时,不能再创建有新的 __weak引用,否则会crash

递归调用父类的-dealloc

如果是 MRC 代码,则需要手动释放实例变量

最后调用NSObject的dealloc

NSObject的dealloc会调用 _objc_rootDealloc(self);

_objc_rootDealloc(id obj) NSObject.mm 1838行

_objc_rootDealloc(id obj)
{
    //是否还活着 断言
    assert(obj);
   //调用 objc_object::rootDealloc()
    obj->rootDealloc();
}

objc_object::rootDealloc() objc_object.h 415行

objc_object::rootDealloc()
{
    //是否使用TaggedPointer优化 是直接人突然
    if (isTaggedPointer()) return;  // fixme necessary?

   //不需要处理object_dispose的所有内容
    if (fastpath(isa.nonpointer  &&  
                 !isa.weakly_referenced  &&  
                 !isa.has_assoc  &&  
                 !isa.has_cxx_dtor  &&  
                 !isa.has_sidetable_rc))
    {
        assert(!sidetable_present());
        free(this);
    } 
    else {
       //调用object_dispose
        object_dispose((id)this);
    }
}

object_dispose(id obj) objc-runtime-new.mm 6313行

id object_dispose(id obj)
{
    //是否为nil 直接返回
    if (!obj) return nil;
    //调用 void *objc_destructInstance(id obj)
    objc_destructInstance(obj);    
    free(obj);
    return nil;
}

void *objc_destructInstance(id obj) objc-runtime-new.mm 6290行

void *objc_destructInstance(id obj) 
{
//如果不为nil 才处理
    if (obj) {
        //是否有析构函数  这个bool值取决于当前类以及父类往上是否有实例变量,如果有实例变量当前类就有.cxxDestruct,当前类或父类有此方法值=YES,都没有才=NO
        bool cxx = obj->hasCxxDtor();
       //是否有关联对象
        bool assoc = obj->hasAssociatedObjects();
        // This order is important.
      //如果有析构函数 调用 void object_cxxDestruct(id obj)
        if (cxx) object_cxxDestruct(obj);
       //如果有关联对象 移除关联对象
        if (assoc) _object_remove_assocations(obj);
        //调用objc_clear_deallocating()清空引用计数表
        obj->clearDeallocating();
    }
    return obj;
}

void object_cxxDestruct(id obj) objc-class.mm 473行

void object_cxxDestruct(id obj)
{
   //如果为nil 直接retun
    if (!obj) return;
   //是否使用TaggedPointer优化 是直接return
    if (obj->isTaggedPointer()) return;
   //调用 static void object_cxxDestructFromClass(id obj, Class cls)
    object_cxxDestructFromClass(obj, obj->ISA());
}

static void object_cxxDestructFromClass(id obj, Class cls) objc-class 447行

static void object_cxxDestructFromClass(id obj, Class cls)
{
    void (*dtor)(id);

    // Call cls's dtor first, then superclasses's dtors.

    //往父类递归调用.cxxDestruct 直到hasCxxDtor=NO return结束
    for ( ; cls; cls = cls->superclass) {
        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);
        }
    }
}

.cxx_destruct

ARC下拥有实例变量才会有这个方法,通过Clang CodeGen生成,MRC都需要手动release所以不需要
ARC下会遍历当前对象所有的实例变量通过objc_storeStrong() release掉
具体实现过程:https://blog.sunnyxx.com/2014/04/02/objc_dig_arc_dealloc/

void objc_removeAssociatedObjects(id object) objc-runtime 635行

void objc_removeAssociatedObjects(id object) 
{
    if (object && object->hasAssociatedObjects()) {
        _object_remove_assocations(object);
    }
}

void _object_remove_assocations(id object) objc-references 316行

关联对象都存放在AssociationsHashMap中,以obj为key,以存放关联对象的ObjectAssociationMap为value,然后拿到ObjectAssociationMap中的所有ObjcAssociation对象,然后此对象调用ReleaseValue(),继而调用releaseValue,然后调用objc_release
void _object_remove_assocations(id object) {
    vector< ObjcAssociation,ObjcAllocator > 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());
    }
};
static void releaseValue(id value, uintptr_t policy) {
    if (policy & OBJC_ASSOCIATION_SETTER_RETAIN) {
        return objc_release(value);
    }
}

void objc_clear_deallocating(id obj) NSObject.mm 1705行

void 
objc_clear_deallocating(id obj) 
{
    assert(obj);

    if (obj->isTaggedPointer()) return;
    obj->clearDeallocating();
}

objc_object::clearDeallocating() objc-object.h 399行

inline void 
objc_object::clearDeallocating()
{
    if (slowpath(!isa.nonpointer)) {
        // Slow path for raw pointer isa.
       //调用sidetable_clearDeallocating()把对象的weak指针置nil,把对象的计数引用移除
        sidetable_clearDeallocating();
    }
    else if (slowpath(isa.weakly_referenced  ||  isa.has_sidetable_rc)) {
        /判断是否有过弱引用   是否因为计数太大有多个sidetable
        // Slow path for non-pointer isa with weak refs and/or side table data.
       //调用clearDeallocating_slow();内部再分开判断各自实现sidetable_clearDeallocating的内容
        clearDeallocating_slow();
    }

    assert(!sidetable_present());
}
相信看了上面的源码分析 对于下面这种图 父类有属性,关联对象,子类有属性关联对象,此时创建个[SubClass new]然后释放掉,这几个类的dealloc打印顺序是什么应该也清楚了,当然属性之间dealloc顺序,关联对象之间顺序还需要注意,同一个类多个属性的dealloc顺序是倒序,
  • 属性列表的顺序:

分类属性1,分类属性2,类扩展属性1,类扩展属性2,类属性1,类属性2

  • 属性的dealloc销毁顺序是:

类扩展属性2,类扩展属性1,类属性2,类属性1,然后再销毁父类的属性

关联对象添加的成员变量是先销毁子类的成员变量,在销毁父类的,在同一个类里添加的顺序不一定,因为底层是存储在无序map中,所以dealloc顺序不一定

屏幕快照 2018-11-15 下午2.00.48.png

runtime源代码下载地址
搜索objc4 选择数字最大的即为最新的(并不是最下面的就是最新的,看数字大小)

你可能感兴趣的:(Objc对象的销毁过程)