本文會繼續深刻學習OC內存管理,內容主要參考iOS高級編程,Objective-C基礎教程,瘋狂iOS講義,是我學習內存管理的筆記objective-c
MRC
>(Mannul Reference Counting)ARC
>(Automatic Reference Count)GC
>(Garbage Collection)因爲iOS系統不支持垃圾回收,因此咱們在iOS開發中只能使用MRC和ARC來進行內存管理,本文再也不介紹Objective-C中的垃圾回收機制,可是此處注意Objective-C中是存在垃圾回收機制的
內存泄露
:再也不須要的對象沒有釋放編程
引發的問題
:程序的內存佔有量不斷增長,最終會被耗盡致使程序崩潰野指針
:沒有進行初始化得指針函數
引發的問題
:浪費內存資源,若是調用程序會出現未知的結果,甚至致使程序崩潰學習
懸空指針
:一個指針指向一個被銷燬的對象指針
引發的問題
:調用懸空指針指向的屬性或者方法時,程序會出現未知的結果,甚至致使程序崩潰調試
殭屍對象
:過分釋放的對象code
引發的問題
:對象
MRC
>(Mannul Reference Counting)引用計數
:Objective-C中引入了引用計數這一機制來跟蹤並處理對象的生命週期,繼承
管理方式
:每一個對象都有一個與之關聯的整數,這個整數被稱爲引用計數,在Objective-C中,經過不一樣的方法能夠對引用計數進行操做,具體的處理以下表:教程
對象操做 | Objective-C方法 | 對應的操做結果 |
---|---|---|
生成並持有對象 | alloc , new , copy ,mutableCopy 等方法 |
生成對象並設置引用計數 =1 |
持有對象 | reatain 方法 |
使引用計數 +1 |
釋放對象 | release 方法 |
使引用計數 -1 |
廢棄對象 | dealloc 方法---系統自動調用 |
引用計數 =0 時調用 |
關於delloc
方法:dealloc方法繼承自NSObject
,所以全部的對象都具備此方法,當一個對象的引用計數爲0時,也就意味着沒有任何程序須要此對象,系統會回收該對象所佔用的內存,在系統銷燬對象以前,會自動調用該對象的dealloc方法來執行一些回收操做,若是該對象還持有其餘對象的引用,咱們必須重寫dealloc方法來釋放該對象引用的其餘對象(一般就是使用該對象的release方法)
引用計數機制回收對象的說明
:若是一個對象的引用計數爲0,則代表程序已經再也不須要它,這時系統會自動回收該對象所佔內存,相反,若是一個對象的引用計數不爲0,系統就不該該回收,也不會回收它所佔的內存
關於retainCount方法
:Objective-C提供了retainCount方法來返回一個對象當前的引用計數
如何重寫dealloc方法
:
- (void)dealloc { // 處理該對象的其餘引用(經過release方法) /** 回調父類的dealloc方法 */ [super dealloc]; }
alloc
+alloc +allocWithZone: class_createInstance //此方法能夠經過objc4中的runtime/objc-runtime-new.mm確認 calloc // 分配內存塊
retainCount
-retainCount __CFDoExternRefOperation // 此函數根據retain,retainCount,release操做進行分發,調用__CFBasicHashXXX方法 CFBasicHashGetCountOfKey
retain
-retain __CFDoExternRefOperation CFBasicHashAddValue
release
-release __CFDoExternRefOperation CFBasicHashRemoveValue // 當此函數返回0時, -release調用dealloc方法
1.1 使用alloc
new
copy
mutableCopy
建立的對象只能本身持有
id obj1 = [[NSObject alloc] init]; id obj2 = [NSObject new]; id obj3 = [NSObject copy]; id obj4 = [NSObject mutableCopy];
1.2 使用以上名稱的開頭的方法也意味着本身生成並持有對象
alloc
NewObject
new
NewObject
copy
NewObject
mutableCopy
NewObject
2.1 非alloc
new
copy
mutableCopy
生成的對象,變量obj自己不持有該對象
id obj1 = [NSMutableArray array]; id obj2 = [NSDictionary dictionary];
2.2 經過retain方法,非經過alloc
new
copy
mutableCopy
生成的對象,能夠成爲本身持有的對象
id obj = [NSMutableArray array]; [obj retain];
3.1 釋放經過alloc
new
copy
mutableCopy
生成的對象,一旦不在須要,務必要使用release方法釋放
id obj = [[NSObject alloc] init]; [obj release];
3.2 用retain方法持有的非本身生成的對象,一旦再也不須要,也必定要使用release釋放
id obj = [NSMutableArray array]; [obj retain]; // 經過retain方法持有對象 [obj release]; // 在不須要時也要經過release方法釋放對象
3.3 用某個方法生成對象,並將其做爲方法的返回值,這時咱們該如何處理
3.3.1 經過alloc
new
copy
mutableCopy
或其餘符合命名規則的方法生成的對象,只須要原封不動的返回就能讓調用方也持有該對象
- (id)allocObject { id obj = [[NSObject alloc] init]; return obj; } - (id)allocObjectWithObject:(id)obj { id object = [obj allocObject]; return object; }
3.3.2 若是持有非本身生成的對象,例如[NSMutableArray array]生成的對象,咱們要使用autorelease方法釋放
注:命名規則
:用來取得誰都不持有的對象的方法名不能以alloc
new
copy
mutableCopy
開頭
- (id)object { id obj = [NSMutableArray array]; [obj autorelease]; return obj; }
3.3.3 autorelease
方法:提供了這樣的功能,使對象在超出指定的生存範圍時自動並正確釋放(調用release方法)
4.1 經過alloc
new
copy
mutableCopy
方法或者經過retain方法持有的對象,一旦再也不須要時,必須進行釋放,除此以外其餘方法得到的對象絕對不能釋放,一旦釋放會形成程序崩潰
4.2 本身持有的對象釋放後再次釋放,形成僵死對象,引發程序崩潰或在訪問廢棄的對象時崩潰
id obj = [[NSObject alloc] init]; [obj release]; [obj release]; // 再次釋放