作为一个有好几年的开发人员来说,有时候我们知道怎么用,但是不知道为什么要这么用,也就是知其然,不知其所以然,对于以前的我来说我是一个不求甚解的人。但是作为一个专业的技术人,要想更上一层楼。还是要知其所以然的为好,特别是技术面试,就能决定一个人的内力到底有多深了。
实战
首先我们创建两个属性,一个copy修饰, 一个strong修饰
@interface ViewController ()
@property(nonatomic, strong) NSString *strongStr;
@property(nonatomic, copy) NSString *copyedStr;
@end
第一种情况
- (void)testOne {
NSString *str = [NSString stringWithFormat:@"ikonan"];
self.strongStr = str;
self.copyedStr = str;
// %p str 内容内存首地址
// %p &str 变量str内存的首地址
NSLog(@"originString: %p, %p, %@",str, &str, str);
NSLog(@"strongString: %p, %p, %@",_strongStr, &_strongStr, self.strongStr);
NSLog(@"copyedString: %p, %p, %@",_copyedStr, &_copyedStr, self.copyedStr);
str = @"abc";
NSLog(@"originString: %p, %p, %@",str, &str, str);
NSLog(@"strongString: %p, %p, %@",_strongStr, &_strongStr, self.strongStr);
NSLog(@"copyedString: %p, %p, %@",_copyedStr, &_copyedStr, self.copyedStr);
//运行结果
originString: 0xa006e616e6f6b696, 0x16b1a53a8, ikonan
strongString: 0xa006e616e6f6b696, 0x10520d190, ikonan
copyedString: 0xa006e616e6f6b696, 0x10520d198, ikonan
originString: 0x104c600f0, 0x16b1a53a8, abc
strongString: 0xa006e616e6f6b696, 0x10520d190, ikonan
copyedString: 0xa006e616e6f6b696, 0x10520d198, ikonan
}
结论
当string为不可变字符串时(这种情况strong 和 copy没区别)
不管是strong还是copy属性的对象,其指向的地址都是同一个,即为string指向的地址。
当string的值发生改变时,两个对象的值也保持原来的值
第二种情况
- (void)testTwo {
NSMutableString *str = [[NSMutableString alloc] initWithString:@"ikonan"];
self.strongStr = str;
self.copyedStr = str;
NSLog(@"originString: %p, %p, %@",str, &str, str);
NSLog(@"strongString: %p, %p, %@",_strongStr, &_strongStr, self.strongStr);
NSLog(@"copyedString: %p, %p, %@",_copyedStr, &_copyedStr, self.copyedStr);
[str appendString:@"123"];
NSLog(@"originString: %p, %p, %@",str, &str, str);
NSLog(@"strongString: %p, %p, %@",_strongStr, &_strongStr, self.strongStr);
NSLog(@"copyedString: %p, %p, %@",_copyedStr, &_copyedStr, self.copyedStr);
}
//运行结果
originString: 0x1c0252570, 0x16b7f53a8, ikonan
strongString: 0x1c0252570, 0x14bd07ba0, ikonan
copyedString: 0xa006e616e6f6b696, 0x14bd07ba8, ikonan
originString: 0x1c0252570, 0x16b7f53a8, ikonan123
strongString: 0x1c0252570, 0x14bd07ba0, ikonan123
copyedString: 0xa006e616e6f6b696, 0x14bd07ba8, ikonan
结论
当string为可变字符串时(copy 深拷贝, strong 就是浅拷贝)
- 此时copy属性字符串已不再指向string字符串对象,而是深拷贝了string字符串,并让_copyedStr对象指向这个字符串
- _strongStr与string是指向同一对象,所以_strongString的值也会跟随着改变(需要注意的是,此时_strongStr的类型实际上是NSMutableString,而不是NSString);而_copyedStr是指向另一个对象的,所以并不会改变。
总结
在声明NSString属性时,到底是选择strong还是copy,可以根据实际情况来定。不过,一般我们将对象声明为NSString时,都不希望它改变,所以大多数情况下,我们建议用copy,以免因可变字符串的修改导致的一些非预期问题。