天天看点

iOS修饰符copy以及strong区别

iOS开发-------属性用copy、strong修饰的区别      Copy,Strong的区别需要了解点内存管理的知识,Strong是ARC下引入的修饰,相当于手动管理内存(MRC)下的retain,在相关代码下,常常看到有的人用copy修饰NSString,NSArray,NSDictionary..等存在可变与不可变之分的对象,常常会用copy,而不是strong,下面代码来解释一下strong与copy的区别:

先说明一下什么叫做浅拷贝,什么叫做深拷贝;

浅Copy:可以理解为指针的复制,只是多了一个指向这块内存的指针,共用一块内存。

深Copy:理解为内存的复制,两块内存是完全不同的,也就是两个对象指针分别指向不同的内存,互不干涉。

首先在类延展中声明两个属性变量

[objc]  view plain  copy

  1. @property (nonatomic, strong)NSString * stringStrong;   //strong修饰的字符串对象  
  2. @property (nonatomic, copy)NSString * stringCopy;       //copy修饰的字符串对象  

接着创建两个不可变字符串(NSString)

[objc]  view plain  copy

  1. //新创建两个NSString对象  
  2. NSString * strong1 = @"I am Strong!";  
  3. NSString * copy1 = @"I am Copy!";  

将两个属性分别进行赋值

[objc]  view plain  copy

  1. //初始化两个字符串  
  2. self.stringStrong = strong1;  
  3. self.stringCopy = copy1;  

分别打印一下四个变量的内存地址:

[objc]  view plain  copy

  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

  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

  1. //新创建两个NSMutableString对象  
  2. NSMutableString * mutableStrong = [NSMutableString stringWithString:@"StrongMutable"];  
  3. NSMutableString * mutableCopy = [NSMutableString stringWithString:@"CopyMutable"];  

分别对属性再次进行赋值 [objc]  view plain  copy

  1. self.stringStrong = mutableStrong;  
  2. self.stringCopy = mutableCopy;  

分别打印一下四个变量的地址:结果如下:这时就发现了,用strong修饰的字符串依旧进行了浅Copy,而由copy修饰的字符串进行了深Copy,所以mutableStrong与stringStrong指向了同一块内存,而mutableCopy和stringCopy指向的是完全两块不同的内存。

[objc]  view plain  copy

  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

  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

  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

  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

  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等存在可变不可变之分的类对象了,避免出现意外的数据操作.

继续阅读