Runtime維護(hù)了一個(gè)weak表饿凛,用于存儲(chǔ)指向某個(gè)對象的所有weak指針各薇。weak表其實(shí)是一個(gè)hash(哈希)表,Key是所指對象的地址常熙,Value是weak指針的地址(這個(gè)地址的值是所指對象的地址)數(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)建對應(yīng)的弱引用表涧至。
3腹躁、釋放時(shí),調(diào)用clearDeallocating函數(shù)南蓬。clearDeallocating函數(shù)首先根據(jù)對象地址獲取所有weak指針地址的數(shù)組纺非,然后遍歷這個(gè)數(shù)組把其中的數(shù)據(jù)設(shè)為nil,最后把這個(gè)entry從weak表中刪除赘方,最后清理對象的記錄烧颖。
1.實(shí)現(xiàn)weak后,為什么對象釋放后會(huì)自動(dòng)為nil
runtime對注冊的類窄陡, 會(huì)進(jìn)行布局炕淮,對于weak對象會(huì)放入一個(gè)hash表中。 用weak指向的對象內(nèi)存地址作為key跳夭,當(dāng)此對象的引用計(jì)數(shù)為0的時(shí)候會(huì)dealloc涂圆,假如weak指向的對象內(nèi)存地址是a,那么就會(huì)以a為鍵币叹, 在這個(gè)weak表中搜索润歉,找到所有以a為鍵的weak對象,從而設(shè)置為nil颈抚。
2.當(dāng)weak引用指向的對象被釋放時(shí)踩衩,又是如何去處理weak指針的呢
1、調(diào)用objc_release
2、因?yàn)閷ο蟮囊糜?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ì)過程如下:
a. 從weak表中獲取廢棄對象的地址為鍵值的記錄
b. 將包含在記錄中的所有附有 weak修飾符變量的地址,賦值為 nil
c. 將weak表中該記錄刪除
d. 從引用計(jì)數(shù)表中刪除廢棄對象的地址為鍵值的記錄