iOS 底层原理

weak指针实现自动设置为nil

2020-08-11  本文已影响0人  iOS打工犭袁

在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]; 
};

由上可知:

  1. referent是存储被引用对象的地址.
  2. inline_referrers是用来装weak指针的数组,不过数量只有WEAK_INLINE_COUNT=4个.
  3. referrers也是存储weak指针的数组,但是当inline_referrers不够的时候才会使用的.
二、系统在对象销毁时的做法

在对象销毁时会做的事情,根据源码追踪重要的步骤:

  1. 调用dealloc
  2. _objc_rootDealloc(self);
  3. obj->rootDealloc();
  4. object_dispose(this);
  5. 先调用objc_destructInstance(obj);清楚对象相关联的东西, 之后再调用free(obj);释放对象。
  6. objc_destructInstance(obj);会做的事情
// This order is important.
 if (cxx) object_cxxDestruct(obj); 
 if (assoc) _object_remove_assocations(obj);// 清除属性关联
 obj->clearDeallocating();

  1. clearDeallocating函数里面会调用clearDeallocating_slow();
  2. clearDeallocating_slow();里面会调用weak_clear_no_lock(&table.weak_table, (id)this);
  3. weak_clear_no_lock函数中将referrers数组或者inline_referrers数组遍历,赋值为nil。

收录:原文地址

上一篇下一篇

猜你喜欢

热点阅读