weak原理
Runtime 維護(hù)了一個(gè) weak表,用于存儲(chǔ)指向某個(gè)對(duì)象的所有weak指針巢价。weak表 其實(shí)是一個(gè) hash(哈希)表,Key 是所指對(duì)象的地址,Value是 weak指針 的地址(這個(gè)地址的值是所指對(duì)象指針的地址)數(shù)組贝或。
1、初始化時(shí):runtime會(huì)調(diào)用objc_initWeak函數(shù)锐秦,初始化一個(gè)新的weak指針指向?qū)ο蟮牡刂贰?/p>
2咪奖、添加引用時(shí):objc_initWeak函數(shù)會(huì)調(diào)用 objc_storeWeak() 函數(shù), objc_storeWeak() 的作用是更新指針指向酱床,創(chuàng)建對(duì)應(yīng)的弱引用表羊赵。
3、釋放時(shí)扇谣,調(diào)用clearDeallocating函數(shù)昧捷。clearDeallocating函數(shù)首先根據(jù)對(duì)象地址獲取所有weak指針地址的數(shù)組,然后遍歷這個(gè)數(shù)組把其中的數(shù)據(jù)設(shè)為nil罐寨,最后把這個(gè)entry從weak表中刪除靡挥,最后清理對(duì)象的記錄。
1.實(shí)現(xiàn)weak后衩茸,為什么對(duì)象釋放后會(huì)自動(dòng)為nil
runtime對(duì)注冊(cè)的類(lèi)芹血, 會(huì)進(jìn)行布局贮泞,對(duì)于weak對(duì)象會(huì)放入一個(gè)hash表中。 用weak指向的對(duì)象內(nèi)存地址作為key幔烛,當(dāng)此對(duì)象的引用計(jì)數(shù)為0的時(shí)候會(huì)dealloc啃擦,假如weak指向的對(duì)象內(nèi)存地址是a,那么就會(huì)以a為鍵饿悬, 在這個(gè)weak表中搜索令蛉,找到所有以a為鍵的weak對(duì)象,從而設(shè)置為nil狡恬。
2.當(dāng)weak引用指向的對(duì)象被釋放時(shí)珠叔,又是如何去處理weak指針的呢
1、調(diào)用objc_release
2弟劲、因?yàn)閷?duì)象的引用計(jì)數(shù)為0祷安,所以執(zhí)行dealloc
3、在dealloc中兔乞,調(diào)用了_objc_rootDealloc函數(shù)
4汇鞭、在_objc_rootDealloc中,調(diào)用了object_dispose函數(shù)
5庸追、調(diào)用objc_destructInstance
6霍骄、最后調(diào)用objc_clear_deallocating,詳細(xì)過(guò)程如下:
a. 從weak表中獲取廢棄對(duì)象的地址為鍵值的記錄
b. 將包含在記錄中的所有附有 weak修飾符變量的地址,賦值為 nil
c. 將weak表中該記錄刪除
d. 從引用計(jì)數(shù)表中刪除廢棄對(duì)象的地址為鍵值的記錄
sideTable
struct SideTable {
// 保證原子操作的自旋鎖
spinlock_t slock;
// 引用計(jì)數(shù)的 hash 表
RefcountMap refcnts;
// weak 引用全局 hash 表
weak_table_t weak_table;
}
struct weak_table_t {
// 保存了所有指向指定對(duì)象的 weak 指針
weak_entry_t *weak_entries;
// 存儲(chǔ)空間
size_t num_entries;
// 參與判斷引用計(jì)數(shù)輔助量
uintptr_t mask;
// hash key 最大偏移值
uintptr_t max_hash_displacement;
};
鏈接:http://www.reibang.com/p/b93d61418f17