1.runtime中如何實(shí)現(xiàn)weak
-
生成weak對象
{
//obj是__strong修飾且被賦值的對象
id __weak obj1 = obj;
}
//編譯器的模擬代碼
//轉(zhuǎn)化1
id obj1;
objc_initWeak(&obj1, obj);
objc_destroyWeak(&obj1); //作用域結(jié)束黔酥,釋放對象
//轉(zhuǎn)化2
id obj1;
obj1 = 0;
objc_storeWeak(&obj1, obj);
objc_storeWeak(&obj1, 0);
weak對象有一張weak表(類似引用計(jì)數(shù)表)赎瞎,是作為散列表被實(shí)現(xiàn)有勾。賦值對象(obj)的內(nèi)存地址作為key频伤,weak對象(obj1)的內(nèi)存地址作為value存儲(chǔ)蔬崩。一個(gè)objc可以賦值給多個(gè)weak對象铺纽,所以一個(gè)key可以對應(yīng)多個(gè)value趟咆。
-
釋放weak對象
(1) objc_release
(2) 引用計(jì)數(shù)為0呵扛,執(zhí)行dealloc
(3) _objc_rootDealloc
(4) object_dispose
(5) objc_destructInstance
(6) objc_clear_deallocating
主要講一下第(6)步,它做的事情有:
1)從weak表中獲取weak對象的地址為鍵值的記錄
2)將包含在記錄中所有附有__weak修飾符變量的地址隔节,賦值為nil
3)從weak表中刪除該記錄
4)從引用計(jì)數(shù)表中刪除weak對象的地址為鍵值的記錄
2.__weak對象與autoreleasepool的關(guān)系
__weak修飾符的變量鹅经,會(huì)注冊到autoreleasepool中
{
//obj是__strong修飾且被賦值的對象
id __weak obj1 = obj;
NSLog(@"%@", obj1);
}
//編譯器的模擬代碼
id obj1;
objc_initWeak(&obj1, obj);
id tmp = objc_loadWeakRetained(&obj1);
objc_autorelease(tmp);
NSLog(@"%@", obj1);
objc_destroyWeak(&obj1); //作用域結(jié)束,釋放對象
objc_loadWeakRetained函數(shù)取出附有__weak修飾符變量所引用的對象怎诫,并retain
objc_autorelease函數(shù)將對象注冊到autoreleasepool中
所以瘾晃,如果大量使用附有weak修飾符的變量,注冊到autoreleasepool的對象也會(huì)大量增加幻妓。解決辦法:最好先暫時(shí)將weak對象賦值給strong修飾符的變量后再使用