Skip to content

iOS weak修饰的释放则自动被置为nil的实现原理

Deepin edited this page Aug 19, 2021 · 1 revision

Runtime维护着一个Weak表,用于存储指向某个对象的所有Weak指针, 这个表就是sideTable

在开源文件objc4-706中, 可以看到NSObject.mm类文件中对于SideTable的定义如下:

struct SideTable {
    spinlock_t slock;
    RefcountMap refcnts;
    weak_table_t weak_table;

    SideTable() {
        memset(&weak_table, 0, sizeof(weak_table));
    }

    ~SideTable() {
        _objc_fatal("Do not delete SideTable.");
    }

    void lock() { slock.lock(); }
    void unlock() { slock.unlock(); }

    // Address-ordered lock discipline for a pair of side tables.

    template<bool HaveOld, bool HaveNew>
    static void lockTwo(SideTable *lock1, SideTable *lock2);
    template<bool HaveOld, bool HaveNew>
    static void unlockTwo(SideTable *lock1, SideTable *lock2);
};

SideTable 结构体重定了几个非常重要的变量。

// The order of these bits is important.
#define SIDE_TABLE_WEAKLY_REFERENCED (1UL<<0)
#define SIDE_TABLE_DEALLOCATING      (1UL<<1)  // MSB-ward of weak bit
#define SIDE_TABLE_RC_ONE            (1UL<<2)  // MSB-ward of deallocating bit
#define SIDE_TABLE_RC_PINNED         (1UL<<(WORD_BITS-1))

#define SIDE_TABLE_RC_SHIFT 2
#define SIDE_TABLE_FLAG_MASK (SIDE_TABLE_RC_ONE-1)

Weak表是Hash表,Key是所指对象的地址,Value是Weak指针地址的数组

在对象被回收的时候,经过层层调用,会最终触发下面的方法将所有Weak指针的值设为nil。

runtime源码,objc-weak.m 的 arr_clear_deallocating 函数

weak指针的使用涉及到Hash表的增删改查,有一定的性能开销.

Clone this wiki locally