iOS記憶體管理
iOS記憶體管理從整體來講,就四點:
①自己產生的對象,自己持有;
②非自己產生的對象,自己也能持有;
③不再需要自己持有的對象時釋放;
④非自己持有的對象無法釋放。 MRC下的記憶體管理
在進行MRC記憶體管理時,我們需要注意幾點:
①自己產生的對象,自己持有,比如new/alloc/copy/mutableCopy建立;
②非自己產生的對象,自己也能持有,比如retain持有;
③不再需要自己持有的對象時釋放,用release釋放;
④非自己持有的對象無法釋放,比如對象release以後已經釋放,再次release會引起崩潰。 ARC下的記憶體管理
在進行ARC記憶體管理時,我們需要注意幾點:
①block中循環參考問題;
②CoreFoundation和Foundation架構橋接轉換;
③手動開闢的記憶體需要自己釋放;
④在類中,dealloc方法中對KVO和Notification置為nil。
⑤不能顯示的調用retain、release、dealloc方法
⑥使用自動釋放池時,用@autoreleasepool塊來代替NSAutoreleasePool對象。
⑦由於ARC中記憶體管理是由編譯器來做的,而C語言中沒有方法來管理結構體成員的生命週期,所以OC中的變數不能作為C語言結構體的成員。
⑧在MRC中可以顯示的轉換id和void *,但是在ARC中需要通過__bridge進行橋接轉換。 從所有權修飾符來看
記憶體管理中的所有權修飾符分為四種:
__strong、__weak、__autorelease、__unsafe_unretained。前三個所有權修飾符可以保證初始化為nil,最後一個所有權修飾符不能自動置為nil。
①__strong修飾符是id類型和物件類型預設的修飾符,__strong修飾符的引入,解決了MRC中需要手動release來解決記憶體管理問題。
②__weak修飾符用來打破循環參考,造成循環參考的情況有兩種,一種是對象間互相強引用,一種是對象對自身的強引用。
③__weak用於iOS5以後打破循環參考,iOS5之前使用__unsafe_unretained來打破循環參考,在ARC中使用__unsafe_unretained時,該修飾符所修飾的對象,其記憶體不屬於編譯器的管理範圍。
④__unsafe_unretained修飾對象時,必須保證該對象沒有廢棄,否則可能引起崩潰。 __strong所有權修飾符和__weak所有權修飾符
__strong所有權修飾符:
①通過alloc初始化,虛擬碼實現
id obj = objc_msgSend(obj, @selector(alloc));
obj_msgSend(obj, @selector(init));
obj_release(obj);
②通過類方法初始化,虛擬碼實現
id obj = objc_msgSend(NSMutableArray, @selector(array));
objc_retainAutoreleasedReturnValue(obj);
objc_release(obj);
__weak所有權修飾符:
第一點:附有__weak修飾符的變數所引起的對象被廢棄,則將nil賦值給該變數。
id __weak obj1 = obj;
上面代碼,通過虛擬碼實現
id obj1;
objc_initWeak(&obj1,obj);
objc_destoryWeak(&obj1);
定義函數objc_storeWeak,把第二個參數的賦值對象的地址作為索引值,將第一個參數的附有__weak修飾符的變數的地址註冊到weak表中,如果第二個參數為0,則把變數的地址從weak表中刪除。
以上虛擬碼,也可通過以下虛擬碼實現
id obj1 = 1;
objc_storeWeak(&obj1,obj);
objc_storeWeak(&obj1,0);
weak表與引用計數表相同,都是作為散列表被實現。如果使用weak表,將廢棄對象的地址作為索引值進行檢索,就能高速的擷取對應的附有__weak修飾符的變數地址。另外,由於一個對象可同時賦值給多個附有__weak修飾符的變數中,所以一個索引值,可註冊多個變數的地址。
釋放weak修飾的對象時,程式的執行步驟分為四步:
①從weak表中擷取廢棄對象的地址為索引值的記錄;
②將包含在記錄中的所有附有__weak修飾符變數的地址,賦值為nil;
③從weak表中刪除該記錄;
④從引用計數表中刪除廢棄對象的地址為索引值的記錄。
第二點:附有__weak修飾符的變數,即是使用註冊到autoreleasepool中的對象
id __weak obj1 = obj;
NSLog(@“%@”,obj1);
上面代碼通過虛擬碼實現
聲明兩個函數,objc_loadWeakRetained函數取出附有__weak修飾符變數所引用的對象並retain,objc_autorelease函數將對象註冊到自動釋放池中。
id obj1;
objc_initWeak(&obj1,obj);
id tmp = objc_loadWeakRetaind(&obj1);
objc_autorelease(tmp);
NSLog(@“%@”,tmp);
objc_destoryWeak(&obj1); 屬性修飾符中的所有權修飾符
屬性修飾符中,assgin和unsafe_unretained的所有權修飾符是__unsafe_unretained、strong和retain、copy的所有權修飾符是__strong,weak的所有權修飾符是__weak。