虽然网上有很多解释,但还是自己测试一遍看看结果。
interface定义两个字符串,分别copy和strong修饰
@interface ViewController ()
@property (nonatomic, copy) NSString *strCopy1;
@property (nonatomic, strong) NSString *strStrong1;
1:使用不可变字符串赋值
NSString *str111 = @"name";
self.strCopy1 = str111,
self.strStrong1 = str111;
NSLog(@"%p->内存%p-----", &str111, str111);
NSLog(@"%p->内存%p-----", &_strCopy1, _strCopy1);
NSLog(@"%p->内存%p-----", &_strStrong1, _strStrong1);
结果:
2017-07-16 11:21:57.305 strong-copy[3211:556935] 0x7fff5b10ca08->内存0x104af3078-----
2017-07-16 11:21:57.305 strong-copy[3211:556935] 0x7f841ec051f8->内存0x104af3078-----
2017-07-16 11:21:57.305 strong-copy[3211:556935] 0x7f841ec05200->内存0x104af3078-----
可以看到,三个不同的指针指向同一个内存地址,这里并没有发现copy和strong有什么区别。
2:使用可变字符串赋值
NSMutableString *str333 = [NSMutableString stringWithFormat:@"qwe"];
self.strCopy1 = str333;
self.strStrong1 = str333;
[str333 appendString:@"sss"];
NSLog(@"%p->内存%p-----%@", &str333, str333, str333);
NSLog(@"%p->内存%p-----%@", &_strCopy1, _strCopy1, _strCopy1);
NSLog(@"%p->内存%p-----%@", &_strStrong1, _strStrong1, _strStrong1);
结果
2017-07-16 11:28:52.466 strong-copy[3267:566054] 0x7fff5df88a00->内存0x608000264cc0-----qwesss
2017-07-16 11:28:52.466 strong-copy[3267:566054] 0x7f97a8607f88->内存0xa000000006577713-----qwe
2017-07-16 11:28:52.466 strong-copy[3267:566054] 0x7f97a8607f90->内存0x608000264cc0-----qwesss
发现self.strCopy1执行了深拷贝,而self.strStrong1则依然指向原来的内存地址。
结论:发现copy和strong的区别在于针对可变对象时,copy会深拷贝一个新的内存地址,防止对象再次被修改。
接下里,我们看看self.xxx和_xxx的区别。
大家都知道,当我们使用@property声明对象xxx时,会自动生成一个_xxx的变量,这时发现self.xxx和_xxx都可以调用。但是这两者具体有什么区别?
度娘了一下,发现都有这么一句话:self.xxx是访问属性的,而_xxx是访问实例变量的。
不明白没关系,直接代码测试:
NSMutableString *str333 = [NSMutableString stringWithFormat:@"qwe"];
_strCopy1 = str333; //将这里的self.xxx改_xxx
_strStrong1 = str333;
[str333 appendString:@"sss"];
NSLog(@"%p->内存%p-----%@", &str333, str333, str333);
NSLog(@"%p->内存%p-----%@", &_strCopy1, _strCopy1, _strCopy1);
NSLog(@"%p->内存%p-----%@", &_strStrong1, _strStrong1, _strStrong1);
2017-07-16 11:45:24.625 strong-copy[3325:585666] 0x7fff5e38ea00->内存0x618000074c00-----qwesss
2017-07-16 11:45:24.625 strong-copy[3325:585666] 0x7f818ac08c98->内存0x618000074c00-----qwesss
2017-07-16 11:45:24.625 strong-copy[3325:585666] 0x7f818ac08ca0->内存0x618000074c00-----qwesss
结果发现不论是copy还是strong修饰,使用_xxx赋值的内存地址都没有变化。
结论1:self.xxx会调用set和get的方法,而_xxx不会调用。所有在使用懒加载的时候需要使用self.xxx访问;
结论2:self.xxx和_xxx在引用的时候不会有区别,是同一个指针,但是赋值是有区别的 self.xxx=aa 首先把xxx retaincount -1然后retain aa _xxx复制直接指向oo 不存在retain这一步操作。
总结:1使用@property声明对象时,字符串尽量使用copy修饰;
2使用@property声明对象时,尽量使用self.xxx访问。
当然了,具体情况需要具体对待。