美文网首页将来跳槽用iOS
对象回收时Weak指针自动被置为nil的实现原理

对象回收时Weak指针自动被置为nil的实现原理

作者: 北辰青 | 来源:发表于2017-01-13 11:33 被阅读0次

    前言

    我们都知道Weak指针不会增加所引用对象的计数,并在引用对象被回收的时候自动被置为nil。通常用于解决循环引用问题。那么,自动被置为nil内部是如何实现的呢?

    内部实现 —— Weak表

    Runtime维护了一个Weak表,用于存储指向某个对象的所有Weak指针。Weak表其实是一个哈希表,Key是所指对象的地址,Value是Weak指针的地址(这个地址的值是所指对象的地址)的数组。

    在对象被回收的时候,经过层层调用,会最终触发下面的方法将所有Weak指针的值设为nil。(具体定义在objc-weak.m中)

    PRIVATE_EXTERN void

    arr_clear_deallocating(weak_table_t *weak_table, id referent) {

    {

    weak_entry_t *entry = weak_entry_for_referent(weak_table, referent);

    if (entry == NULL) {

    /// XXX shouldn't happen, but does with mismatched CF/objc

    //printf("XXX no entry for clear deallocating %p\n", referent);

    return;

    }

    // zero out references

    for (int i = 0; i < entry->referrers.num_allocated; ++i) {

    id *referrer = entry->referrers.refs[i].referrer;

    if (referrer) {

    if (*referrer == referent) {

    *referrer = nil;

    }

    else if (*referrer) {

    _objc_inform("__weak variable @ %p holds %p instead of %p\n", referrer, *referrer, referent);

    }

    }

    }

    weak_entry_remove_no_lock(weak_table, entry);

    weak_table->num_weak_refs--;

    }

    }

    简单来说,这个方法首先根据对象地址获取所以Weak指针地址的数组,然后遍历这个数组把其中的数据设为nil,最后把这个entry从Weak表中删除。

    这里只简单说说对象回收时,Weak指针如何设为nil,至于Weak指针如何注册到Weak表中、如何维护可以参考objc-weak.m中的其它源码。从实现中可以看出,Weak指针的使用涉及到Hash表的增删改查,有一定的性能开销。

    相关文章

      网友评论

        本文标题:对象回收时Weak指针自动被置为nil的实现原理

        本文链接:https://www.haomeiwen.com/subject/zkkdbttx.html