在編程語言中是少不了對內存的管理的,內存對於計算機來說是寶貴的資源,所以對使用不到的資源進行回收是很有必要的。OC中使用引用計數和垃圾回收來管理內存,在OC中爲每個對象分配一個引用計數器,當對象剛剛被創建時其初始值爲1,當有某段代碼需要訪問一個對象是時,會將該對象的引用計數器加1(通過retain來實現);當訪問一個對象結束時,會將該對象的引用計數器減1(通過release來實現);當計數器爲0時,該對象佔用的內存空間會被收回。在NSObject類有一個retainCount方法,調用該方法可獲取當前對象的引用計數值。
在XCode4以後的版本採取自動引用計數(Automatic Reference Counting)簡稱ARC, 默認的是ARC模式,在ARC下是不能直接調用retain,release, releaseCount等方法的,需要在XCode中進行設置,設置如下: 把Objective-C Automatic Reference Counting 改爲NO,即可。
之前提到的NSOject類裏有個方法,retainCount可以獲取當前對象的引用計數的值,廢話少說上點代碼吧。
1. 用可變的數組結合着可變的字符串來觀察一下retainCount的變化。
(1).先創建一個可變數組對象,在創建一個可變字符串對象;
(2).然後往可變數組裏添加可變的字符串,觀察可變字符串的retainCount的變化。
(3).在可變數組中移除一個str,觀察retainCount的變化
(4)我們爲什麼要用可變的字符串呢?稍後會提到爲什麼。
- <span style="font-size:18px;">//用可變數組來測試內存的訪問
- NSMutableArray *array = [NSMutableArray arrayWithCapacity:3];
- //可變的字符串
- NSMutableString *str = [[NSMutableString alloc] initWithString:@"aa"];
- //這時的retain = 1;
- NSLog(@"新建str時的 strRetain = %d",(int)[str retainCount]);
- //把可變字符串對象傳入到可變數組中 NSMutalbe的retain會自動加一
- //把對象傳給另一個對象,此時的retain = 2;
- [array addObject:str];
- //retain =3;
- [array addObject:str];
- NSLog(@"添加兩個str元素後 strRetain = %d",(int)str.retainCount);
- //移除元素
- [array removeObjectAtIndex:0];
- NSLog(@"移除一個元素後 strRetain = %d",(int)str.retainCount);</span>
運行的結果:
- <span style="font-size:18px;">2014-08-03 19:53:24.449 Memory[2448:303] 新建str時的 strRetain = 1
- 2014-08-03 19:53:24.449 Memory[2448:303] 添加兩個str元素後 strRetain = 3
- 2014-08-03 19:53:24.450 Memory[2448:303] 移除一個元素後 strRetain = 2</span>
2.NSString的retainCount的變化
用NSString聲明的字符串變量的retainCount變化由你初始化字符串時的方式決定
1. 用NSString *str = @”ludashi”;定義變量
用上面的方法定義的字符串是常量字符串,他的retianCount爲-1或不定,不會隨着retian或者release變化而變化
demo如下:
- <span style="font-size:18px;">NSString *string = @"aa";
- NSLog(@"str常量的retainCount = %d",(int)string.retainCount);//retainCount = -1
- [string retain]; //沒用
- NSLog(@"str常量的retainCount = %d",(int)string.retainCount);//retainCount = -1</span>
- <span style="font-size:18px;">2014-08-03 20:01:31.360 Memory[2463:303] str常量的retainCount = -1
- 2014-08-03 20:01:31.362 Memory[2463:303] str常量的retainCount = -1</span>
2.使用stringWithFormat創建的NSString爲變量,系統會進行引用計數。
demo:
- <span style="font-size:18px;">/*使用stringWithFormat創建的NSString爲變量,系統會進行引用計數。*/
- NSString *string1 = [NSString stringWithFormat:@"aaaa"];
- [string1 retain];
- NSLog(@"NSStringFomatRetainCount = %d",(int)string1.retainCount);//retainCount = 2</span>
- <span style="font-size:18px;">NSStringFomatRetainCount = 2</span>
3 .stringWithString取決於後面跟的string, 後面string的retainCount是多少那麼用stringWithString創建的對象就爲多少
demo:
- <span style="font-size:18px;">/*stringWithString取決於後面跟的string, 後面string的retainCount是多少那麼用stringWithString創建的對象就爲多少*/
- NSString *string2 = [NSString stringWithString:string];
- NSLog(@"傳入字符串常量 RetainCount = %d", (int)string2.retainCount);//retainCount = -1
- NSString *string3 = [NSString stringWithString:string1];
- NSLog(@"傳入的變量FomatRetainCount = %d",(int)string1.retainCount); //retainCount = 3
- NSLog(@"傳入的變量RetainCount = %d", (int)string3.retainCount);//retainCount = 3</span>
運行結果:
- 2014-08-03 20:18:37.240 Memory[2499:303] 傳入字符串常量 RetainCount = -1
- 2014-08-03 20:18:37.240 Memory[2499:303] 傳入的變量FomatRetainCount = 3
- 2014-08-03 20:18:37.240 Memory[2499:303] 傳入的變量RetainCount = 3
Objective-C中得ARC(Automatic Reference Counting)
1.ARC中應注意的問題:
(1). 不能顯式調用dealloc語句, 或者實現或調用retain, release, retianCount 和 autorelease等方法。
(2).不能調用@selector (retain) ,@selector (release)等;
(3).不能使用NSAutoreleasePool對象, 用@autoreleasepool塊來代替;
(4).不能用開頭new的名稱來定義一個屬性,除非你定義一個別的getter名稱。
2.ARC特性
ARC增加了新的屬性定義關鍵字,strong來代替retain,表示強引用。用weak來代替assign表示弱引用。