__weak修飾符,是我們經常用來解決循環引用的良藥利器,它展現出如此強大的魔力,我卻一無所知。所以我決定去看一看它的實現。
在看了《Objective-C高級編程》一書以后,關于__weak的實現理念,我用簡單的方式概括一下為:
id obj = 1;
id __weak obj1 = obj;
/*編譯器模擬代碼*/
id obj1;
obj1 = 0;
objc_storeWeak(&obj1,obj);
objc_storeWeak(&obj1,0);
關于objc_storeWeak的底層實現呢,下次再看。
底層實現理念為將obj的地址作為鍵值,然后將__weak修飾符修飾的obj1的地址注冊到weak表中。
可以簡單的看作是{&obj:&obj1},便于理解。
如果第二個參數是0,則把變量的地址從weak表中刪除。
由于一個對象可以同時同時賦值給多個__weak修飾符的變量中,所以對于一個鍵值,可注冊多個變量的地址。
__weak修飾符所修飾的變量地址作為鍵值是注冊到一個weak表中的,
這里為了便于理解,可以簡單的看作是{&obj:@[&obj1,&obj2,&obj3......]}。
釋放對象時,程序的動作運行:
1.先調用objc_release
2.因為引用計數為0所以執行dealloc
3._objc_rootDealloc
4.object_dispose
5.objc_destructInstance
6.objc_clear_deallocating
當obj將要被被廢棄的時候,會通過obj的地址在weak表找尋到所對應的所有__weak修飾符變量的地址,賦值為nil,然后將記錄刪除,再從引用計數表中刪除廢棄對象的地址為鍵值的記錄。
但是由此可知,如果大量的使用附有__weak修飾符的變量,則會消耗相應的CPU資源,所以良策是只在需要避免循環引用時使用__weak修飾符。