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(@"\n"); 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(@"\n");
当一个不可变字符串(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(@"\n"); 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(@"\n");
打印结果如下:
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:我来了