1. 程式人生 > >assign,copy,retain之間的區別

assign,copy,retain之間的區別

copy: 建立一個索引計數為1的物件,然後釋放舊物件
retain:釋放舊的物件,將舊物件的值賦予輸入物件,再提高輸入物件的索引計數為1

Copy其實是建立了一個相同的物件,而retain不是:
比如一個NSString物件,地址為0×1111,內容為@”STR”
Copy到另外一個NSString之後,地址為0×2222,內容相同,新的物件retain為1,舊有物件沒有變化
retain到另外一個NSString之後,地址相同(建立一個指標,指標拷貝),內容當然相同,這個物件的retain值+1
也就是說,retain是指標拷貝,copy是內容拷貝。
一般情況下:
使用assign: 對基礎資料型別 (NSInteger,CGFloat)和C資料型別(int, float, double, char, 等等) 
使用copy: 對NSString 

使用retain: 對其他NSObject和其子類 

舉個例子: NSString *str = [[NSString alloc] initWithString:@'abc']; 上面一段程式碼會執行以下兩個動作: 1 在堆上分配一段記憶體用來儲存@'abc' ,比如:記憶體地址為0X1111 內容為 'abc' 2 在棧上分配一段記憶體用來儲存str,比如:地址為0XAAAA 內容自然為0X1111 下面分別看下(assign,retain,copy): 1.assign的情況:NSString *newStr = [str assign]; 此時newStr和str完全相同,地址都是0XAAAA ,內容為0X1111 ,即newStr只是str的別名,對任何一個操作就等於對另一個操作。因此retainCount不需要增加.
2.retain的情況:NSString * newStr = [str retain]; 此時newStr的地址不再為0XAAAA,可能為0XAABB,但是內容依然為0X1111.因此newStr和str都可以管理'abc'所在的記憶體。因此 retainCount需要增加1. 3.copy的情況:NSString * newStr = [str copy]; 此時會在堆上重新開闢一段記憶體存放@'abc',比如0X1122,內容為@'abc,同時會在棧上為newStr分配空間,比如地址:0XAACC,內容為0X1122,因此retainCount增加1供newStr來管理0X1122這段記憶體.

3、示例:環境是在不選擇ARC的環境下

新建Person類,使他繼承與NSObject,在.m檔案中實現dealloc方法:
  1. - (void) dealloc    
  2. {    
  3.     NSLog (@"dealloc called. Bye Bye.");    
  4.     [super dealloc];    
  5. }   
在引用計數為0時,這個方法就會被呼叫,證明這個物件被銷燬。 建立一個物件,列印它的引用計數
  1. Person *person = [[Person alloc] init];  
  2. NSLog(@"物件person的retainCount: %d", [person retainCount]);  

物件personretainCount: 1

我們增加1

  1. Person *person = [[Person alloc] init];  
  2.  NSLog(@"物件person的retainCount: %d",[person retainCount] );  
  3.  [person retain];  
  4.  NSLog(@"物件person的retainCount: %d", [person retainCount]);  

列印結果:

物件personretainCount: 1

物件personretainCount: 2

和傳說的一樣,retainCount增加了。可以有在release時,減少到1時就不再減 了

  1. Person *person = [[Person alloc] init];  
  2. NSLog(@"物件person的retainCount: %d",[person retainCount] );  
  3. [person retain];  
  4. NSLog(@"物件person的retainCount: %d", [person retainCount]);  
  5. [person release];  
  6. [person release];  
  7. NSLog(@"物件person的retainCount: %d", [person retainCount]);  
這個程式碼最後打印出來的retainCount是0嗎?列印結果:
  1. 2012-07-05 16:05:29.830 ObjectiveCTest[2847:f803] 物件person的retainCount: 1  
  2. 2012-07-05 16:05:29.831 ObjectiveCTest[2847:f803] 物件person的retainCount: 2  
  3. 2012-07-05 16:05:29.831 ObjectiveCTest[2847:f803] dealloc called. Bye Bye.  
  4. 2012-07-05 16:05:29.832 ObjectiveCTest[2847:f803] 物件person的retainCount: 1  
震驚了,第一次release 時retainCount減1了,再release , d物件的dealloc called了,但是retainCount 還是1.在stackoverflow.com的查了一下,有人說這個retainCount沒什麼用。。。。可以事實的確如retainCount是1,物件被幹掉了。有人說,要把person = nil。這樣retainCount就是0了。試了下,nil的 retainlCount永遠是0.這個賦值沒有意義。