天天看點

IOS開發底層之Weak底層原理實作一、weak基本用法

一、weak基本用法

weak是弱引用,用weak來修飾、描述所引用對象的計數器并不會加1,而且weak會在引用對象被釋放的時候自動置為nil,這也就避免了野指針通路壞記憶體而引起奔潰的情況,另外weak也可以解決循環引用。

拓展:為什麼修飾代理使用weak而不是用assign?

assign可用來修飾基本資料類型,也可修飾OC的對象,但如果用assign修飾對象類型指向的是一個強指針,當指向的這個指針釋放之後,它仍指向這塊記憶體,必須要手動給置為nil,否則會産生野指針,如果還通過此指針操作那塊記憶體,會導緻EXC_BAD_ACCESS錯誤,調用了已經被釋放的記憶體空間;而weak隻能用來修飾OC對象,而且相比assign比較安全,如果指向的對象消失了,那麼它會自動置為nil,不會導緻野指針。

二、weak原理概括

weak表其實是一個哈希表,key是所指對象的指針,value是weak指針的位址數組。(value是數組的原因是:因為一個對象可能被多個弱引用指針指向)

Runtime維護了一張weak表,用來存儲某個對象的所有的weak指針。

weak原理實作過程三步驟

  1. 初始化開始時,會調用objc_initWeak函數,初始化新的weak指針指向對象的位址
IOS開發底層之Weak底層原理實作一、weak基本用法

  2.緊接着,objc_initWeak函數裡面會調用objc_storeWeak() 函數,objc_storeWeak() 函數的作用是用來更新指針的指向,建立弱引用表。

IOS開發底層之Weak底層原理實作一、weak基本用法

   3.在最後會調用clearDeallocating函數。而clearDeallocating函數首先根據對象的位址擷取weak指針位址的數組,然後緊接着周遊這個數組,将其中的數組開始置為nil,把這個entry從weak表中删除,最後一步清理對象的記錄。

拓展:詳細步驟

  1. 初始化開始時,會調用objc_initWeak函數,初始化新的weak指針指向對象的位址

當我們初始化weak變量時,runtime會調用NSObject.mm中的objc_initWeak,而objc_initWeak函數裡面的實作如下:

IOS開發底層之Weak底層原理實作一、weak基本用法
id objc_initWeak(id *location, id newObj) {
// 檢視對象執行個體是否有效,無效對象直接導緻指針釋放
    if (!newObj) {
        *location = nil;
        return nil;
    }
    // 這裡傳遞了三個 bool 數值
    // 使用 template 進行常量參數傳遞是為了優化性能
    return storeWeakfalse/*old*/, true/*new*/, true/*crash*/>
    (location, (objc_object*)newObj);
}
           
IOS開發底層之Weak底層原理實作一、weak基本用法

通過上面代碼可以看出,objc_initWeak()函數首先判斷指針指向的類對象是否有效,無效,直接傳回;否則通過storeWeak()被注冊為一個指向value的_weak對象

  2. objc_initWeak函數裡面會調用objc_storeWeak() 函數,objc_storeWeak() 函數的作用是用來更新指針的指向,建立弱引用表。

  3..在最後會調用clearDeallocating函數。而clearDeallocating函數首先根據對象的位址擷取weak指針位址的數組,然後緊接着周遊這個數組,将其中的數組開始置為nil,把這個entry從weak表中删除,最後一步清理對象的記錄。

問:當weak指向的對象被釋放時,如何讓weak指針置為nil的呢?

IOS開發底層之Weak底層原理實作一、weak基本用法
1、調用objc_release
2、因為對象的引用計數為0,是以執行dealloc
3、在dealloc中,調用了_objc_rootDealloc函數
4、在_objc_rootDealloc中,調用了object_dispose函數
5、調用objc_destructInstance
6、最後調用objc_clear_deallocating,詳細過程如下:
   a. 從weak表中擷取廢棄對象的位址為鍵值的記錄
   b. 将包含在記錄中的所有附有 weak修飾符變量的位址,指派為   nil
   c. 将weak表中該記錄删除
   d. 從引用計數表中删除廢棄對象的位址為鍵值的記錄
           
IOS開發底層之Weak底層原理實作一、weak基本用法

本文講述了weak底層實作原理,也是面試經常被問到的一點,希望對大家有所幫助,謝謝!