對象回收時Weak指針自動被置為nil的實現(xiàn)原理

前言

我們都知道Weak指針不會增加所引用對象的計數(shù),并在引用對象被回收的時候自動被置為nil。通常用于解決循環(huán)引用問題。那么,自動被置為nil內(nèi)部是如何實現(xiàn)的呢?

內(nèi)部實現(xiàn) —— Weak表

Runtime維護了一個Weak表,用于存儲指向某個對象的所有Weak指針。Weak表其實是一個哈希表,Key是所指對象的地址,Value是Weak指針的地址(這個地址的值是所指對象的地址)的數(shù)組。

在對象被回收的時候,經(jīng)過層層調(diào)用,會最終觸發(fā)下面的方法將所有Weak指針的值設(shè)為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--;

}

}

簡單來說,這個方法首先根據(jù)對象地址獲取所以Weak指針地址的數(shù)組,然后遍歷這個數(shù)組把其中的數(shù)據(jù)設(shè)為nil,最后把這個entry從Weak表中刪除。

這里只簡單說說對象回收時,Weak指針如何設(shè)為nil,至于Weak指針如何注冊到Weak表中、如何維護可以參考o(jì)bjc-weak.m中的其它源碼。從實現(xiàn)中可以看出,Weak指針的使用涉及到Hash表的增刪改查,有一定的性能開銷。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容