一、weak 基本用法
weak 是弱引用,用 weak 來修飾、描述所引用對象的計數(shù)器并不會增加,而且 weak 會在引用對象被釋放的時候自動置為 nil,這也就避免了野指針訪問壞內(nèi)存而引起奔潰的情況,另外 weak 也可以解決循環(huán)引用。
拓展:為什么修飾代理使用 weak 而不是用 assign?
assign 可用來修飾基本數(shù)據(jù)類型,也可修飾 OC 的對象,但如果用 assign 修飾對象類型指向的是一個強指針,當指向的這個指針釋放之后,它仍指向這塊內(nèi)存,必須要手動給置為 nil,否則會產(chǎn)生野指針,如果還通過此指針操作那塊內(nèi)存,會導致 EXC_BAD_ACCESS 錯誤,調(diào)用了已經(jīng)被釋放的內(nèi)存空間;而 weak 只能用來修飾 OC 對象,而且相比 assign 比較安全,如果指向的對象消失了,那么它會自動置為 nil,不會導致野指針。
二、weak 原理概括
weak 表其實是一個哈希表,key 是所指對象的指針,value 是 weak 指針的地址數(shù)組。(value 是數(shù)組的原因是:因為一個對象可能被多個弱引用指針指向)
Runtime 維護了一張 weak 表,用來存儲某個對象的所有的 weak 指針。
weak 原理實現(xiàn)過程三步驟
Runtime會維護一個weak表,用于維護指向?qū)ο蟮乃衱eak指針。weak表是一個哈希表,其key為所指對象的指針,value為weak指針的地址數(shù)組。
具體過程如下:
1、初始化時:runtime會調(diào)用objc_initWeak函數(shù),初始化一個新的weak指針指向?qū)ο蟮牡刂贰?/p>
2、添加引用時:objc_initWeak函數(shù)會調(diào)用 objc_storeWeak() 函數(shù),更新指針指向,創(chuàng)建對應的弱引用表。
3、釋放時,調(diào)用clearDeallocating函數(shù)。clearDeallocating函數(shù)首先根據(jù)對象地址獲取所有weak指針地址的數(shù)組,然后遍歷這個數(shù)組把其中的數(shù)據(jù)設為nil,最后把這個entry從weak表中刪除,最后清理對象的記錄。