在ARC中,weak指针修饰的变量会在指向的对象销毁时自动置为nil,系统是怎么做到的呢?这里从本质和源码出发来解释。源码
iOS系统中维护着一个SideTables的哈希表,这个哈希表用来管理所有对象的引用计数和weak指针。
一、找到weak指针存储的位置
SideTables哈希表里面装着的元素的key为对象地址,value为SideTable的结构体!
struct SideTable {
spinlock_t slock;
RefcountMap refcnts; // 引用计数
weak_table_t weak_table; // 弱引用表
}
由上面可知weak_table_t是系统保存weak指针的结构。
存储weak指针的结构体weak_table_t
struct weak_table_t {
weak_entry_t *weak_entries;
size_t num_entries;
};
typedef DisguisedPtr<objc_object *> weak_referrer_t;
#define WEAK_INLINE_COUNT 4
struct weak_entry_t {// 本来是一个C++结构体, 简化后如下
DisguisedPtr<objc_object> referent;
weak_referrer_t *referrers;
weak_referrer_t inline_referrers[WEAK_INLINE_COUNT];
};
由上可知:
-
referent是存储被引用对象的地址. -
inline_referrers是用来装weak指针的数组,不过数量只有WEAK_INLINE_COUNT=4个. -
referrers也是存储weak指针的数组,但是当inline_referrers不够的时候才会使用的.
二、系统在对象销毁时的做法
在对象销毁时会做的事情,根据源码追踪重要的步骤:
- 调用
dealloc _objc_rootDealloc(self);obj->rootDealloc();object_dispose(this);- 先调用
objc_destructInstance(obj);清楚对象相关联的东西, 之后再调用free(obj);释放对象。 -
objc_destructInstance(obj);会做的事情
// This order is important.
if (cxx) object_cxxDestruct(obj);
if (assoc) _object_remove_assocations(obj);// 清除属性关联
obj->clearDeallocating();
-
clearDeallocating函数里面会调用clearDeallocating_slow(); -
clearDeallocating_slow();里面会调用weak_clear_no_lock(&table.weak_table, (id)this);。 -
weak_clear_no_lock函数中将referrers数组或者inline_referrers数组遍历,赋值为nil。
收录:原文地址












网友评论