天天看點

iOS開發 -- 屬性用copy、strong修飾的差別

Copy,Strong的差別需要了解點記憶體管理的知識,Strong是ARC下引入的修飾,相當于手動管理記憶體(MRC)下的retain,在相關代碼下,常常看到有的人用copy修飾NSString,NSArray,NSDictionary..等存在可變與不可變之分的對象,常常會用copy,而不是strong,下面代碼來解釋一下strong與copy的差別:

先說明一下什麼叫做淺拷貝,什麼叫做深拷貝;

淺Copy:可以了解為指針的複制,隻是多了一個指向這塊記憶體的指針,共用一塊記憶體。

深Copy:了解為記憶體的複制,兩塊記憶體是完全不同的,也就是兩個對象指針分别指向不同的記憶體,互不幹涉。

首先在類延展中聲明兩個屬性變量

[objc]  view plain  copy  

iOS開發 -- 屬性用copy、strong修飾的差別
iOS開發 -- 屬性用copy、strong修飾的差別
  1. @property (nonatomic, strong)NSString * stringStrong;   //strong修飾的字元串對象  
  2. @property (nonatomic, copy)NSString * stringCopy;       //copy修飾的字元串對象  

接着建立兩個不可變字元串(NSString)

[objc]  view plain  copy  

iOS開發 -- 屬性用copy、strong修飾的差別
iOS開發 -- 屬性用copy、strong修飾的差別
  1. //新建立兩個NSString對象  
  2. NSString * strong1 = @"I am Strong!";  
  3. NSString * copy1 = @"I am Copy!";  

将兩個屬性分别進行指派

[objc]  view plain  copy  

iOS開發 -- 屬性用copy、strong修飾的差別
iOS開發 -- 屬性用copy、strong修飾的差別
  1. //初始化兩個字元串  
  2. self.stringStrong = strong1;  
  3. self.stringCopy = copy1;  

分别列印一下四個變量的記憶體位址:

[objc]  view plain  copy  

iOS開發 -- 屬性用copy、strong修飾的差別
iOS開發 -- 屬性用copy、strong修飾的差別
  1. NSLog(@"strong1 = %p",strong1);  
  2. NSLog(@"stringStrong = %p",self.stringStrong);  
  3. NSLog(@"copy1 = %p",copy1);  
  4. NSLog(@"stringCopy = %p",self.stringCopy);  

結果如下:可以看出,此時無論是strong修飾的字元串還是copy修飾的字元串,都進行了淺Copy.

[plain]  view plain  copy  

iOS開發 -- 屬性用copy、strong修飾的差別
iOS開發 -- 屬性用copy、strong修飾的差別
  1. 2016-02-29 18:59:06.332 StrongOrCopy[5046:421886] strong1 = 0x10a0b3078  
  2. 2016-02-29 18:59:06.332 StrongOrCopy[5046:421886] stringStrong = 0x10a0b3078  
  3. 2016-02-29 18:59:06.332 StrongOrCopy[5046:421886] copy1 = 0x10a0b3098  
  4. 2016-02-29 18:59:06.332 StrongOrCopy[5046:421886] stringCopy = 0x10a0b3098  

如果建立兩個不可變字元串對象(NSMutableString)呢

[objc]  view plain  copy  

iOS開發 -- 屬性用copy、strong修飾的差別
iOS開發 -- 屬性用copy、strong修飾的差別
  1. //新建立兩個NSMutableString對象  
  2. NSMutableString * mutableStrong = [NSMutableString stringWithString:@"StrongMutable"];  
  3. NSMutableString * mutableCopy = [NSMutableString stringWithString:@"CopyMutable"];  

分别對屬性再次進行指派 [objc]  view plain  copy  

iOS開發 -- 屬性用copy、strong修飾的差別
iOS開發 -- 屬性用copy、strong修飾的差別
  1. self.stringStrong = mutableStrong;  
  2. self.stringCopy = mutableCopy;  

分别列印一下四個變量的位址:結果如下:這時就發現了,用strong修飾的字元串依舊進行了淺Copy,而由copy修飾的字元串進行了深Copy,是以mutableStrong與stringStrong指向了同一塊記憶體,而mutableCopy和stringCopy指向的是完全兩塊不同的記憶體。

[objc]  view plain  copy  

iOS開發 -- 屬性用copy、strong修飾的差別
iOS開發 -- 屬性用copy、strong修飾的差別
  1. 2016-02-29 18:59:06.332 StrongOrCopy[5046:421886] mutableStrong = 0x7fccba425d60  
  2. 2016-02-29 18:59:06.332 StrongOrCopy[5046:421886] stringStrong = 0x7fccba425d60  
  3. 2016-02-29 18:59:06.332 StrongOrCopy[5046:421886] mutableCopy = 0x7fccba40d7c0  
  4. 2016-02-29 18:59:06.333 StrongOrCopy[5046:421886] stringCopy = 0x7fccba4149e0  

那麼有什麼用呢,執行個體來看一下有什麼差別:

首先是對不可變字元串進行操作:

[objc]  view plain  copy  

iOS開發 -- 屬性用copy、strong修飾的差別
iOS開發 -- 屬性用copy、strong修飾的差別
  1. //新建立兩個NSString對象  
  2. NSString * strong1 = @"I am Strong!";  
  3. NSString * copy1 = @"I am Copy!";  
  4. //初始化兩個字元串  
  5. self.stringStrong = strong1;  
  6. self.stringCopy = copy1;  
  7. //兩個NSString進行操作  
  8. [strong1 stringByAppendingString:@"11111"];  
  9. [copy1 stringByAppendingString:@"22222"];  

分别對在字元串後面進行拼接,當然這個拼接對原字元串沒有任何的影響,因為不可變自字元串調用的方法都是有傳回值的,原來的值是不會發生變化的.列印如下,對結果沒有任何的影響:

[plain]  view plain  copy  

iOS開發 -- 屬性用copy、strong修飾的差別
iOS開發 -- 屬性用copy、strong修飾的差別
  1. 2016-02-29 19:15:26.729 StrongOrCopy[5146:439360] strong1 = I am Strong!  
  2. 2016-02-29 19:15:26.729 StrongOrCopy[5146:439360] stringStrong = I am Strong!  
  3. 2016-02-29 19:15:26.729 StrongOrCopy[5146:439360] copy1 = I am Copy!  
  4. 2016-02-29 19:15:26.729 StrongOrCopy[5146:439360] stringCopy = I am Copy!  

然後是對可變字元串進行操作:

[objc]  view plain  copy  

iOS開發 -- 屬性用copy、strong修飾的差別
iOS開發 -- 屬性用copy、strong修飾的差別
  1. //新建立兩個NSMutableString對象  
  2. NSMutableString * mutableStrong = [NSMutableString stringWithString:@"StrongMutable"];  
  3. NSMutableString * mutableCopy = [NSMutableString stringWithString:@"CopyMutable"];  
  4. //初始化兩個字元串  
  5. self.stringStrong = mutableStrong;  
  6. self.stringCopy = mutableCopy;  
  7. //兩個MutableString進行操作  
  8. [mutableStrong appendString:@"Strong!"];  
  9. [mutableCopy appendString:@"Copy!"];  

           再來看一下結果:對mutableStrong進行的操作,由于用strong修飾的stringStrong沒有進行深Copy,導緻共用了一塊記憶體,當mutableStrong對記憶體進行了操作的時候,實際上對stringStrong也進行了操作;   相反,用copy修飾的stringCopy進行了深Copy,也就是說stringCopy與mutableCopy用了兩塊完全不同的記憶體,是以不管mutableCopy進行了怎麼樣的變化,原來的stringCopy都不會發生變化.這就在日常中避免了出現一些不可預計的錯誤。 [objc]  view plain  copy  

iOS開發 -- 屬性用copy、strong修飾的差別
iOS開發 -- 屬性用copy、strong修飾的差別
  1. 2016-02-29 19:20:27.652 StrongOrCopy[5245:446189] stringStrong = StrongMutableStrong!  
  2. 2016-02-29 19:20:27.652 StrongOrCopy[5245:446189] mutableStrong = StrongMutableStrong!  
  3. 2016-02-29 19:20:27.652 StrongOrCopy[5245:446189] stringCopy = CopyMutable  
  4. 2016-02-29 19:20:27.652 StrongOrCopy[5245:446189] mutableCopy = CopyMutableCopy!  

     這樣看來,在不可變對象之間進行轉換,strong與copy作用是一樣的,但是如果在不可變與可變之間進行操作,那麼樓主比較推薦copy,這也就是為什麼很多地方用copy,而不是strong修飾NSString,NSArray等存在可變不可變之分的類對象了,避免出現意外的資料操作.