在日常的编程中经常会使用NSString,但是NSString到底是使用copy修饰还是使用strong进行修饰呢?或者说NSString什么时候使用copy
什么时候使用strong
呢?
- 首先需要知道的是
copy
的作用,当我们使用copy
去修饰NSString的时候,就是想让这个NSString不受外部的影响,比如说self.a = b
,当b改变的时候,a不会受到影响还是原来的值,这样保证了安全性
当我们使用@property (nonatomic, copy) NSString *a;
并且进行赋值self.a = b ;
- 如果b是一个不可变的变量,例如NSString类型,这个时候其实是进行了一次浅拷贝,也就是说这个时候,不管是strong还是copy属性的对象,其指向的地址都是同一个,即为b指向的地址,在MRC环境下的效果都是使b指向的对象的引用计数+1;
- 如果b是一个可变的变量,例如NSMutableString 类型,这个时候就有所不同了,因为copy修饰的属性会进行一次深拷贝,也就是说其会
创建一个新的对象
,另外需要注意的是,这个copy属性对象的类型始终是NSString,而不是NSMutableString,因此其是不可变的。;
当我们使用@property (nonatomic, strong) NSString *a;
并且进行赋值self.a = b ;
- 无论b是可变的类型或是不可变的类型,都不会创建一个新的对象,效果都是a指向了b指向的对象,在MRC环境下,就是b指向的对象的引用计数+1
- 这种情况带来了一个问题,如果b为可变类型,并且b在外部进行了一些修改,这样导致了a也会改变,不安全;另外,如果b是一个可变的类型例如NSMutableString 类型,那么,_a的类型实际上就是NSMutableString,因为NSString是NSMutableString的父类,这样是没有问题的
总结:
看了这么多那么到底什么时候使用copy
什么时候使用strong
呢?我的经验是这样的,
- 当你十分确定将要赋一个不变的值的时候用strong,当我们使用copy修饰a,进行赋值的时候,会对b进行一个类型的判断,
if ([str isMemberOfClass:[str class]])
如果是不可变的类型就直接使用strong的策略,即指向b指向的对象进行浅拷贝,如果b是一个可变的类型,那么进行一次深拷贝创建一个新的对象,试想一下,如果是一个你确定的不会变的值我们为什么还需要进行一次类型的判断呢?使用strong能够提升一定的性能; - 但是很多情况下我们并不能确定要赋的值b是什么类型的,所以我们还是使用copy来修饰,这样保证了安全性。