前言: 实际开发中我们声明对象的时候一般使用copy,但是为什么用copy呢 通常声明一个NSString属性时,两种选择
strongorcopy,那到底有什么区别,该如何去使用呢,下面举例说明吧。
举个🌰:
首先在ViewController声明NSString属性
@property (nonatomic, copy) NSString * copystring;
@property (nonatomic, strong) NSString * strongString;
给两个属性赋值,不可变字符串给其赋值,打印查看结果
- (void)viewDidLoad {
[super viewDidLoad];
NSString * string = @"hello,world!";
self.copystring = string;
self.strongString = string;
NSLog(@"string: %p ---%p",string,&string);
NSLog(@"copy: %p ---%p",_copystring,&_copystring);
NSLog(@"strong: %p ---%p",_strongString,&_strongString);
}
打印结果如下:
2020-09-24 string: 0x10d531280 ---0x7ffee2704098
2020-09-24 copy: 0x10d531280 ---0x7f80b2c07648
2020-09-24 strong: 0x10d531280 ---0x7f80b2c07650
打印结果分析
不可变字符串给属性赋值,无论strongorcopy声明的对象,最终指向的其实都是同一个地址,这种情况下,没有区别
那么接下来再看如果是可变对象呢?
将上述NSString * string = @“hello,world!”; 替换为
NSMutableString * string = [NSMutableString stringWithFormat:@"hello,world!"];
打印结果如下:
2020-09-24 string: 0x600002079fe0 ---0x7ffee9879098
2020-09-24 copy: 0x600002e33020 ---0x7ffa77f06408
2020-09-24 strong: 0x600002079fe0 ---0x7ffa77f06410
打印结果分析
使用copy修饰的属性不在指向string对象,而是深拷贝了string字符串,copystring对象指向了这个字符串;而strongString与string是指向了同意对象,所以strongString的值会跟着string改变,也就是说strongString的类型现在已经是NSMutableString,而不是NSString,copyString指向了另一个对象地址,修改string并不会对其造成影响。
结论
实际例子来看,当源字符串为不可变类型时,strong和copy修饰的对象等价,都还是指向了源对象,copy也只是做了一次浅拷贝。
当源字符串为可变类型时,strong属性只是增加了源字符串的引用计数,而copy是产生了新对象做了一次深拷贝,copy属性对象指向这个新对象,深拷贝出来的对象类型是NSString,不可变。
还有一个细节的问题,源字符串是可变类型时,strong是单纯的增加引用计数,而copy做了深拷贝,性能上会有所差异。源字符串为不可变类型时,没有这个问题;
写在最后
平时工作中,在声明NSString时,我们是不希望它被改变的,所以大多数情况下,使用copy来修饰,避免不必要的问题。