內(nèi)存管理方式
- 垃圾回收機制 (Garbage - collection)
程序員只需要開辟內(nèi)存空間,不需要用代碼的形式釋放,系統(tǒng)來判斷哪些空間不再被使用,并回收這些內(nèi)存空間,以便再次分配。整個回收的過程不需要寫任何代碼,由系統(tǒng)自動完成垃圾回收。Java開發(fā)中一直使用的就是垃圾回收技術(shù)。
MRC (Manual Reference Counting)
人工引用計數(shù):內(nèi)存的開辟和釋放都由程序代碼進行控制。相對垃圾回收來說,對內(nèi)存的控制更加靈活,可以在需要釋放的時候及時釋放,對程序員的要求較高,程序員要熟悉內(nèi)存管理的機制。ARC (Auto Reference Counting)
自動引用計數(shù):iOS 5.0的編譯器特性,它允許用戶只開辟空間,不用去釋放空間。它不是垃圾回收!它的本質(zhì)還是MRC,只是編譯器幫程序員默認加了釋放的代碼。
iOS支持兩種內(nèi)存管理方式:ARC 和 MRC
ARC 是基于MRC 的, MRC的內(nèi)存管理機制是: 引用計數(shù)
- C語言中,使用malloc和free 進行堆內(nèi)存的創(chuàng)建和釋放。堆內(nèi)存只有正在使用和銷毀兩種狀態(tài)
- 實際開發(fā)中,可能會遇到兩個以上的指針使用同一塊內(nèi)存。C語言無法記錄內(nèi)存使用者的個數(shù)。


引用計數(shù)
- OC采用引用計數(shù)機制,每個對象都有一個引用計數(shù)器,用來記錄當(dāng)前對象的引用次數(shù)。當(dāng)一個新的引用指向?qū)ο髸r,引用計數(shù)器就+1,去掉一個引用時,引用計數(shù)就-1。當(dāng)引用計數(shù)到0時,該對象的空間就被被系統(tǒng)回收。
| OC對象的操作 | OC中對應(yīng)的方法 |
|---|---|
| 生成對象 | alloc |
| 持有對象 | retain |
| 釋放對象 | release / autorelease |
| 銷毀對象 | dealloc |
- alloc 開辟內(nèi)存空間,讓被開辟的內(nèi)存空間的引用計數(shù)從0變?yōu)?
- retain 引用計數(shù)+1,如果對象之前引用計數(shù)為1,retain之后變?yōu)?
- copy 把某一對象的內(nèi)容拷貝一份,拷貝出新的對象,原有對象的引用計數(shù)不變,新的對象的引用計數(shù)變1
- release 引用計數(shù)立即-1,如果對象之前的引用計數(shù)為4,release之后變?yōu)?,如果之前引用計數(shù)為1,release之后變?yōu)?,內(nèi)存被系統(tǒng)回收
- autorelease 未來的某一時刻引用計數(shù)-1,如果對象之前的引用計數(shù)為4,autorelease之后仍然為4,未來某個時刻會變?yōu)?。通過autoreleasepool自動釋放池,控制autorelease對象的釋放。
屬性的內(nèi)存管理
-
在MRC模式下,同時重寫setter和getter方法來說明各個屬性(@property)修飾符,是如何對內(nèi)存進行管理的。
注意事項:
1.在同時重寫setter和getter方法的時候,系統(tǒng)不會為該屬性生成員變量需
要加 @synthesize propertyName = _propertyName
如下寫法會造成死循環(huán)
2.在set方法中,self.age=age;相當(dāng)于是[self setAge:age];
3.在get方法中,return self.age;相當(dāng)于是[self age];
1.assign
簡單的賦值,不更改引用計數(shù)一般修飾基本數(shù)據(jù)類型(char, short, int, float, double)@synthesize num = _num; @property(nonatomic, assign)NSInteger num; // getter - (NSInteger)num { return _num; } // setter -(void)setNum:(NSInteger)num { _num = num; }2.retain
釋放舊的對象,將舊對象的值賦予輸入對象,再提高輸入對象的索引計數(shù)為1@synthesize name = _name; @property(nonatomic, retain)NSString *name; // getter - (NSString *)name { return [[_name retain] autorelease]; } // setter - (void)setName:(NSString *)name { // 判斷傳進來的字符串和本身屬性的字符串是否相同,不同才賦值 if (name != _name) { [_name release]; // 先將原字符串的引用計數(shù) -1,防止內(nèi)存泄露 _name = [name retain]; // 對新字符串的引用計數(shù) +1 ,防止其他指針釋放該空間 } }3.copy
@synthesize gender = _gender; @property(nonatomic, copy)NSString *gender; // getter - (NSString *)gender { return [[_gender retain] autorelease]; } // setter - (void)setGender:(NSString *)gender { if (gender != _gender) { [_gender release]; // 斷掉之前的聯(lián)系 _gender = [gender mutableCopy]; // 注:mutableCopy 為深拷貝 //對原對象復(fù)制一份放到新的空間,原對象引用計數(shù)沒改變,新對象引用計數(shù)為 +1 } }- 偽拷貝:(只拷貝地址,沒拷貝內(nèi)容)
- 淺拷貝:(會產(chǎn)生新的對象,但是它與原來的對象共用實例變量)
- 深拷貝:(會產(chǎn)生新的對象,并且會把原對象的內(nèi)容完全復(fù)制一份,不會再受原對象影響)
4.strong
strong等同retain
在MRC模式下使用retain, ARC模式下使用strong
5.weak
weak比assign多了一個功能,當(dāng)對象消失后自動把指針變成nil