1. 程式人生 > >copy,retain,strong的區別

copy,retain,strong的區別

      之前的編碼中,對於NSString的property修飾,習慣性使用copy,只是粗略的知道copy屬於深複製,retain/strong屬於淺複製,並沒有對其深究。最近需要詳細瞭解這一塊知識,在網上搜索相關內容,並且用程式碼驗證,檢視對比了記憶體地址,做一些總結。

        一、之前對於copy和retain/strong的區別理解是這樣的:

        copy是複製了源物件所在記憶體空間的資料,放入目的物件指標指向的記憶體空間,並且令目的物件引用計數為1,對於源物件的引用計數沒有影響;源物件內容的改變不會影響到目的物件。

       retain/strong是目的物件指標指向源物件的記憶體空間,源物件的引用計數+1;源物件的改變會影響到目的物件。

      mutablecopy返回的是可變的物件,copy返回的是不可變的物件。

       二、程式碼驗證探究

     1、源物件為不可變 NSString

  1. NSString*str = @"test";  
  2. NSString* retainStr = [str retain];  
  3. NSString* copyStr = [str copy];  
  4. NSMutableString* mcopyStr = [str mutableCopy];  
  5. NSLog(@"str addr = %p",str);  
  6. NSLog(@"retainStr addr = %p",retainStr);  
  7. NSLog(@"copyStr addr = %p",copyStr);  
  8. NSLog(@"mcopyStr addr = %p",mcopyStr);  
輸出如下:
  1. str addr = 0x4598
  2. retainStr addr = 0x4598
  3. copyStr addr = 0x4598
  4. mcopyStr addr = 0x8caf630

分析:

retain的物件毫無懸念,還是源物件的記憶體地址;

copy的物件和我原來想的不一樣,竟然和retain一樣,也是源物件地址;這意味者並沒有對源物件內容進行復制,而只是複製了指標而已。如此看來copy方法並不一定會複製源物件的內容。之所以複製,肯定是因為兩個版本有所不同。而這裡源物件是NSString不可變的,copy返回的也是不可變的,既然都不可變,那麼這裡的副本就沒有多大意義存在,就如同使用字串常量,系統會為我們優化,宣告多個字串,都是不可變且內容相同,那麼系統就只申請一塊記憶體,這個道理是一樣的。指向一塊記憶體就可以了,所以這裡的copy和retain的作用是一樣的。

mutablecopy的物件地址和源物件地址不同,說明重新開闢了記憶體,複製了一個副本。因為mutablecopy返回的物件是可變的,它的變動會影響到源物件,所以需要拷貝一份。

源物件為可變的NSMutableString

  1. NSMutableString* str = [NSMutableString stringWithString:@"test"];  
  2. NSString* retainStr = [str retain];  
  3. NSString* copyStr = [str copy];  
  4. NSMutableString* mcopyStr = [str mutableCopy];  
  5. NSLog(@"str addr = %p",str);  
  6. NSLog(@"retainStr addr = %p",retainStr);  
  7. NSLog(@"copyStr addr = %p",copyStr);  
  8. NSLog(@"mcopyStr addr = %p",mcopyStr);  
輸出結果如下:
  1. str addr = 0x8b7a130
  2. retainStr addr = 0x8b7a130
  3. copyStr addr = 0x8b751d0
  4. mcopyStr addr = 0x8b7a170

分析:

retain仍然和目的物件地址相同;

copy的地址和目的物件地址不相同,是因為源物件是可變的,目的物件不可變,當然需要兩個不同的版本;

mutablecopy形成了一個新的副本。因為兩個物件的改變會影響到對方,所以需要兩個版本。

得到的結論:

1、對於copy來說,如果源物件是不可變的,那麼是淺拷貝,沒有必要深拷貝;如果源物件可變,為了安全性,深拷貝,生成副本。

2、對於mutablecopy來說,不管源物件是否可變,都是深拷貝。

因此我們在設定property的copy屬性時,如果希望物件跟著源物件的值變化,那麼就是用retain;如果希望物件保持獨立的值,那就使用copy。當然這是在源物件為可變的情況下。

上面討論的是NSString相關的retain/copy/mutablecopy,在oc裡面所有實現了NSCopying和NSMutableCopying協議的類,都具有copy和mutablecopy這兩個方法。這裡引出了其他的oc物件的copy特性,它們是什麼樣的,下一篇進行探究。

歡迎指正!