筆記繼續(xù)叠纹,接著內(nèi)存管理、ARC 規(guī)則之后赂乐,本篇將重點記錄下 ARC 內(nèi)存管理方式的實現(xiàn)(__strong
修飾符 和__weak
修飾符)慧库。
ARC 的實現(xiàn)
蘋果的官方說明中稱,ARC 是“由編譯器進(jìn)行內(nèi)存管理”的柠傍,但實際上只有編譯器是無法勝任的麸俘,在此基礎(chǔ)上還需要 Objective-C 運行時庫的協(xié)助。此處圍繞 clang 匯編輸出和 objc4庫(主要是 runtimr/objc-arr.mm)的源代碼進(jìn)行說明惧笛。
__strong 修飾符的實現(xiàn)
下面通過編譯器的模擬代碼从媚,說明在 alloc,new,copy.mutableCopy 的運行?
id __strong obj = [[NSObject alloc] init];
id obj = objc_msgSend(NSObject,@selector(alloc));
objc_msgSend(obj,@selector(init));
obj_release(obj);
上面的模擬轉(zhuǎn)換中患整,可以看出此處是兩次調(diào)用 objc_msgSend
方法(alloc,init)拜效,變量作用域結(jié)束時通過 objc_release
釋放對象。雖然 ARC 有效是各谚,不能使用release
方法紧憾,由此可知編譯器自動插入了 release
。
另外昌渤,我們也要注意除去 alloc,new,copy.mutableCopy 之外的方法說明赴穗,例如 NSMutableArray 中的 array
id __strong obj = [NSMutableArray array];
id obj = objc_msgSend(NSMutableArray,@selector(array));
objc_retainAutoreleasedReturnValue(obj);
objc_release(obj);
進(jìn)一步說明
+ (id)array
{
return [[NSMutableArray alloc] init];
}
id obj = objc_msgSend(MSMutableArray,@selector(alloc));
objc_msgSend(obj,@selector(init));
retrun objc_autoreleaseReturnValue(obj);
此處要注意objc_retainAutoreleasedReturnValue
和objc_autoreleaseReturnValue
兩者,兩者成對出現(xiàn),使函數(shù)最優(yōu)化程序運行般眉。它們可以不將對象注冊到 autoreleasepool
中而直接傳遞了赵,達(dá)到這一過程的的最優(yōu)化。
__weak 修飾符的實現(xiàn)
若附有__weak 修飾符的變量所引用的對象被廢棄甸赃,則將 nil 賦值給該變量柿汛。
id __weak obj1 = obj;
id obj1;
obj_initWeak(&obj1,obj);
objc_destoryWeak(&obj1);
通過 objc_initWeak
函數(shù)初始化附有__weak
修飾符的變量,在變量作用域結(jié)束是通過objc_destoryWeak 釋放該變量埠对。
但此處要注意obj_initWeak
做的事情: 它將附有__weak
修飾符的變量初始化為0后络断,會將賦值的對象作為參數(shù)調(diào)用 objc_storeWeak
函數(shù)。
objc_storeWeak(&obj1,obj);
obj_storeWeak 函數(shù)將第二個參數(shù)的賦值對象的地址作為鍵值项玛,將第一個參數(shù)的附有__weak
修飾符地址注冊到 weak 表(也是一個散列表)中貌笨。如果第二個參數(shù)是0,則將該變量的地址從 weak表中去掉稍计,也就實現(xiàn)了若附有__weak 修飾符的變量所引用的對象被廢棄,則將 nil 賦值給該變量
的功能裕循。
objc_storeWeak(&obj1,obj);
objc_storeWeak(&obj1,0);
使用附有 __weak 修飾符的變量臣嚣,即是使用注冊到
autoreleasepool
中的對象。
id __weak obj1 = obj;
id obj1;
obj_initWeak(&obj1,obj);
id tmp = objc_loadWeakRetained(&obj1);
objc_autorelease(tmp);
objc_destoryWeak(&obj1);
此時增加了兩個步驟:
(1)剥哑、objc_loadWeakRetained
函數(shù)取出附有__weak
修飾符變量所引用的對象并 retain硅则。
(2)、objc_autorelease
函數(shù)將對象注冊到 autoreleasepool
中株婴。
由此可知怎虫,因為附有__weak
修飾符變量所引用的對象像這樣被注冊到 autoreleasepool
中,所以在自動釋放池結(jié)束之前都可以放心使用困介。但是大量使用附有__weak
修飾符的變量大审,注冊到 autoreleasepool
的對象也會大量增加,因此這種大量使用的情況下座哩,最好還是先暫時賦值給附有__strong
修飾符的變量后再使用徒扶。
通過
__weak
、__strong
修飾符的大致實現(xiàn)后根穷,進(jìn)一步認(rèn)識了 ARC 姜骡。同時發(fā)現(xiàn)真是很有需要讀Objc runtime源碼,像里面的一些優(yōu)化屿良,確實做的很到位圈澈,雖說一下子學(xué)不下來具體實現(xiàn),但是思維的學(xué)習(xí)還是可以改善自己的尘惧。