weak 如何将对象置为nil

来源:互联网 发布:淘宝店名设计 编辑:程序博客网 时间:2024/06/11 18:13

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

内部实现 —— Weak表

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

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

  1. PRIVATE_EXTERN void   
  2. arr_clear_deallocating(weak_table_t *weak_table, id referent) {  
  3.     {  
  4.         weak_entry_t *entry = weak_entry_for_referent(weak_table, referent);  
  5.         if (entry == NULL) {  
  6.             /// XXX shouldn’t happen, but does with mismatched CF/objc  
  7.             //printf(“XXX no entry for clear deallocating %p\n”, referent);  
  8.             return;  
  9.         }  
  10.         // zero out references  
  11.         for (int i = 0; i < entry->referrers.num_allocated; ++i) {  
  12.             idid *referrer = entry->referrers.refs[i].referrer;  
  13.             if (referrer) {  
  14.                 if (*referrer == referent) {  
  15.                     *referrer = nil;  
  16.                 }  
  17.                 else if (*referrer) {  
  18.                     _objc_inform(”__weak variable @ %p holds %p instead of %p\n”, referrer, *referrer, referent);  
  19.                 }  
  20.             }  
  21.         }  
  22.   
  23.         weak_entry_remove_no_lock(weak_table, entry);  
  24.         weak_table->num_weak_refs–;  
  25.     }  
  26. }  

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