????????作為一個面試經(jīng)常被問到的問題,iOS weak關(guān)鍵字
基本概念
????????在iOS中,weak的常用來處理NSTimer,delegate,block的循環(huán)引用問題。它是一個弱引用,在對象釋放之后,weak指針自動指向nil,避免野指針,避免錯誤的內(nèi)存訪問。
如何在對象釋放的時候指針置為nil
? ? ? ? 還記得,第一次,接觸到這個問題,只知道weak是弱引用,對象釋放以后,指針會自動賦值為nil。但是為什么在對象釋放后,指針就成了nil,中間進行了什么樣的操作。
? ? ? ? weak說的簡單一些,其實就相當于一個哈希表,在runtime中,是一個覺weak表的東西。將所指對象的地址作為key,vaule是所有指針地址的一個數(shù)組,因為一個對象,可以有多個weak指針指向它。
? ? ? ? 在對象釋放的時候,會調(diào)用一個函數(shù),我們可以看到關(guān)鍵的一些代碼
for(size_t?i?=?0;?i?<?count;?++i)?{
????????objc_object?**referrer?=?referrers[i];
????????if(referrer)?{
????????????if(*referrer?==?referent)?{
????????????????*referrer?=?nil;
????????????}
????????????elseif(*referrer)?{
????????????????_objc_inform("__weak?variable?at?%p?holds?%p?instead?of?%p.?"
?????????????????????????????"This?is?probably?incorrect?use?of?"
?????????????????????????????"objc_storeWeak()?and?objc_loadWeak().?"
?????????????????????????????"Break?on?objc_weak_error?to?debug.\n",
?????????????????????????????referrer,?(void*)*referrer,?(void*)referent);
????????????????objc_weak_error();
????????????}
????????}
????}
????weak_entry_remove(weak_table,?entry);
這里只截取了少量的代碼,可以看到,在對象釋放的時候,會通過key找到weak表中的vaule,從這個數(shù)組中,依次把指針設(shè)為nil,最后,把weak表相關(guān)的記錄也全部刪除。
weak 表實現(xiàn)原理
weak 的實現(xiàn)原理可以概括一下三步:
1、初始化時:runtime會調(diào)用objc_initWeak函數(shù),初始化一個新的weak指針指向?qū)ο蟮牡刂贰?/p>
2、添加引用時:objc_initWeak函數(shù)會調(diào)用 objc_storeWeak() 函數(shù), objc_storeWeak() 的作用是更新指針指向,創(chuàng)建對應(yīng)的弱引用表。
3、釋放時,調(diào)用clearDeallocating函數(shù)。clearDeallocating函數(shù)首先根據(jù)對象地址獲取所有weak指針地址的數(shù)組,然后遍歷這個數(shù)組把其中的數(shù)據(jù)設(shè)為nil,最后把這個entry從weak表中刪除,最后清理對象的記錄。