NSString用copy修饰的原因

一言以蔽之:为了安全

当一个可变字符串(NSMutableString)赋值给一个字符串属性(无论这个字符串是NSString还是NSMutableString)

如果此属性是retain修饰的,就是浅拷贝,引用计数加1。赋值后源字符串改变,这个属性值也跟着改变。

如果此属性是copy修饰的,就是深拷贝,引用计数等于1(因为从堆里新分配一个内存块)。赋值后源字符串改变,这个属性值不会改变。(保证了安全

假设对象有下面4个属性:

1 @property (retain, nonatomic) NSString *retainStr;
2 @property (copy, nonatomic)   NSString *copyStr;
3 @property (retain, nonatomic) NSMutableString *retainMStr;
4 @property (copy, nonatomic)   NSMutableString *copyMStr;
 1     NSMutableString *mStr = [NSMutableString string];
 2     
 3     [mStr setString:@"我没变-------"];
 4     self.retainStr   = mStr;  // 浅拷贝,引用计数加1,
 5     NSLog(@"%ld",[self.retainStr retainCount]);// 2
 6     
 7     self.copyStr     = mStr;    // 深拷贝,
 8     NSLog(@"%ld",[self.copyStr retainCount]);// 1
 9     
10     self.retainMStr = mStr;   // 浅拷贝,引用计数加1,
11     NSLog(@"%ld",[self.retainMStr retainCount]);// 3
12     
13     self.copyMStr   = mStr;   // 深拷贝
14     NSLog(@"%ld",[self.copyMStr retainCount]);// 1
15     
16     
17     
18     NSLog(@"retainStr:%@",  self.retainStr);
19     NSLog(@"copyStr:%@",    self.copyStr);
20     NSLog(@"retainMStr:%@", self.retainMStr);
21     NSLog(@"copyMStr:%@",   self.copyMStr);
22     
23     NSLog(@"
");
24     
25     [mStr setString:@"我变了--------"];
26     
27     NSLog(@"retainStr:%@",  self.retainStr);// 浅拷贝
28     NSLog(@"%ld",[self.retainStr retainCount]);// 3
29     
30     NSLog(@"copyStr:%@",    self.copyStr);// 深拷贝
31     NSLog(@"%ld",[self.copyStr retainCount]);// 1
32     
33     NSLog(@"retainMStr:%@", self.retainMStr);// 浅拷贝
34     NSLog(@"%ld",[self.retainMStr retainCount]);// 3
35     
36     NSLog(@"copyMStr:%@",   self.copyMStr);// 深拷贝
37     NSLog(@"%ld",[self.copyMStr retainCount]);// 1
38     
39     NSLog(@"
");

当一个不可变字符串(NSString)赋值给一个字符串属性(无论这个字符串是NSString还是NSMutableString),就不存在安全性问题,都是深拷贝。此时无论retain还是copy都无所谓。

 1     NSString *str = @"我来了";//[[NSString alloc] initWithString:@"我来了"];//两种方式都一样。都在常量区
 2     
 3     self.retainStr  = str;
 4     self.copyStr    = str;
 5     self.retainMStr = [str mutableCopy];
 6     self.copyMStr   = [str mutableCopy];
 7     
 8     NSLog(@"retainStr:%@",  self.retainStr);
 9     NSLog(@"copyStr:%@",    self.copyStr);
10     NSLog(@"retainMStr:%@", self.retainMStr);
11     NSLog(@"copyMStr:%@",   self.copyMStr);
12     
13     NSLog(@"
");
14     
15     str =@"我走了";//[[NSStringalloc] initWithString:@"我走了"];//两种方式都一样
16     
17     NSLog(@"retainStr:%@",  self.retainStr);
18     NSLog(@"copyStr:%@",    self.copyStr);
19     NSLog(@"retainMStr:%@", self.retainMStr);
20     NSLog(@"copyMStr:%@",   self.copyMStr);
21     
22     NSLog(@"
");

打印结果如下:

1 2016-06-16 12:24:36.818 OCLession9[5278:90728] retainStr:我来了
2 2016-06-16 12:24:36.819 OCLession9[5278:90728] copyStr:我来了
3 2016-06-16 12:24:36.819 OCLession9[5278:90728] retainMStr:我来了
4 2016-06-16 12:24:36.819 OCLession9[5278:90728] copyMStr:我来了
5 2016-06-16 12:24:36.819 OCLession9[5278:90728] 
6 2016-06-16 12:24:36.819 OCLession9[5278:90728] retainStr:我来了
7 2016-06-16 12:24:36.819 OCLession9[5278:90728] copyStr:我来了
8 2016-06-16 12:24:36.819 OCLession9[5278:90728] retainMStr:我来了
9 2016-06-16 12:24:36.819 OCLession9[5278:90728] copyMStr:我来了