初級:
記憶體問題展現在兩個方面
1.記憶體溢出:一旦超出記憶體上限,程式就會 Crash
2.野指針異常:對象記憶體空間已經被系統回收,仍然使用指針操作這塊記憶體.野指針異常是程式 crash 的主要原因.
記憶體管理的方式:
垃圾回收 (gc)
MRC (Manual Reference Count) 人工引用計數
ARC (Auto Reference Count) 自動引用計數
gc : 程式員隻需要開辟記憶體空間,不需要用代碼顯示地釋放,系統來判斷哪些空 間不再被使用,并回收這些記憶體空間,以便再次配置設定.整個回收的過程不需要寫任何代碼,由系統自動完成垃圾回收.
MRC :記憶體的開辟和釋放都由程式代碼進行控制.相對于垃圾回收來說,對記憶體的控制更加靈活,可以在自己需要釋放的時候及時釋放,對程式員的要求較高,程式員要熟悉記憶體管理的機制.
ARC :iOS 5.0的編譯器特性,它允許使用者隻開辟空間,不用去釋放空間.它不是垃圾回收!它的本質還是 MRC, 隻是編譯器幫程式員預設加了釋放的代碼.
iOS 支援兩種記憶體管理方式: ARC 和 MRC
MRC 的記憶體管理機制是:引用計數
ARC 是基于 MRC
引用計數:
OC 采用引用計數機制管理記憶體,當一個新的引用指向對象時,引用計數器就遞增,當去掉一個引用時,引用計數就遞增.當引用計數到零時,該對象就釋放占用的資源.
影響引用計數的方法:
1. +alloc : 開辟記憶體空間,讓被開辟的記憶體空間的引用計數變為1. 這是由0到 1得過程.
2. -retain : 引用計數加1,如果記憶體空間之前引用計數為1,retain 之後變為2,如果引用計數是5,retain 之後變為6.( 相等于自增 )
3. -copy : 把某一記憶體區域的内容拷貝一份,拷貝到新的記憶體空間裡去,被拷貝區域的引用計數不變,新的記憶體區域的引用計數為1.( 原有的不變,新的加1) (淺複制引用計數加1,深複制不變) 淺 copy 相等于 retain 一下
4 .-release : 引用計數減1, 如果記憶體空間之前引用計數為4,release 之後變為3,如果之前引用計數為1,release 之後為0,記憶體被系統回收.( 相等于自減,不是立即減1)
最後一次 release 後,即變為0之後,不能在使用指針和對象的任何東西,使用 的是野指針!也不能進行列印,這是一個錯誤的寫法了!
5. -autorelease : 未來的某一時刻引用計數減1.如果記憶體之前引用計數為4, autorelease之後仍然是4,未來某個時刻會變為3.
dealloc:
- dealloc 是繼承自父類的方法,當對象引用計數為0的時候,由對象自動調用.
我們可以在dealloc 中列印一句話,驗證對象引用計數是否降為0.
- (void)dealloc
{
NSLog(@“%@被銷毀了”,self);
[super dealloc]; // 一定寫在下面 , 先銷毀自己變量的 , 最後銷毀父類變量
}
autoreleasepool 的使用:
通過autoreleasepool 控制 autorelease 對象的釋放.
向一個對象發送 autorelease 消息,這個對象何時釋放,取決于autoreleasepool
先寫的先進來,但是後釋放
寫法:
NSAutoreleasePool *pool = [ [NSAutoreleasePool alloc] init];
Person *p =[ [Person alloc] init];//retainCount為1
[p retain];//retainCount 為2
[p autorelease];//retainCount 為2 未來的某個時刻釋放
[pool release];
NSLog(@“%d”,[p retainCount]);//列印結果為1
在 iOS5之後,不在推薦使用 NSAutoreleasePool 類, 使用@ autoreleasepool{}替代.
寫法為:
autoreleasepool
{
[p autorelease];
[p autorelease];
}
出了大括号,自動釋放池向各個對象發送 release 消息.

記憶體管理的原則:
1.引用計數的增加和減少相等,當引用計數降為0之後,不應該再使用這塊記憶體空間.
2.凡是使用了(隻要你看到了)alloc retain 或 copy 這三個關鍵字,那麼他們肯定是讓記憶體增加了,就需要使用 release 或 autorelease 讓記憶體的引用計數減少.這一段代碼内,增加和減少的次數要相等.
//當 release 和 autorelease 釋放成0的時候,自動掉 dealloc