NSString属性修饰符copy,strong

1,282 阅读2分钟

前言: 实际开发中我们声明对象的时候一般使用copy,但是为什么用copy呢 通常声明一个NSString属性时,两种选择 strong or copy,那到底有什么区别,该如何去使用呢,下面举例说明吧。

举个🌰:

首先在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对象指向了这个字符串;而strongStringstring是指向了同意对象,所以strongString的值会跟着string改变,也就是说strongString的类型现在已经是NSMutableString,而不是NSStringcopyString指向了另一个对象地址,修改string并不会对其造成影响。

结论

实际例子来看,当源字符串为不可变类型时,strongcopy修饰的对象等价,都还是指向了源对象,copy也只是做了一次浅拷贝。

当源字符串为可变类型时,strong属性只是增加了源字符串的引用计数,而copy是产生了新对象做了一次深拷贝,copy属性对象指向这个新对象,深拷贝出来的对象类型是NSString,不可变。

还有一个细节的问题,源字符串是可变类型时,strong是单纯的增加引用计数,而copy做了深拷贝,性能上会有所差异。源字符串为不可变类型时,没有这个问题;

写在最后

平时工作中,在声明NSString时,我们是不希望它被改变的,所以大多数情况下,使用copy来修饰,避免不必要的问题。