咱们在声明一个NSString属性时,对于其内存相关特性,一般有两种选择(基于ARC环境):strong与copy。那这二者有什么区别呢?何时该用strong,何时该用copy呢?让咱们先来看个例子。
性能
示例atom
咱们定义一个类,并为其声明两个字符串属性,以下所示:spa
@interface TestStringClass () @property (nonatomic, strong) NSString *strongString; @property (nonatomic, copy) NSString *copyedString; @end
上面的代码声明了两个字符串属性,其中一个内存特性是strong,一个是copy。下面咱们来看看它们的区别。指针
首先,咱们用一个不可变字符串来为这两个属性赋值,code
- (void)test { NSString *string = [NSString stringWithFormat:@"abc"]; self.strongString = string; self.copyedString = string; NSLog(@"origin string: %p, %p", string, &string); NSLog(@"strong string: %p, %p", _strongString, &_strongString); NSLog(@"copy string: %p, %p", _copyedString, &_copyedString); }
输出结果是: origin string: 0x7fe441592e20, 0x7fff57519a48 strong string: 0x7fe441592e20, 0x7fe44159e1f8 copy string: 0x7fe441592e20, 0x7fe44159e200
这种状况下,无论是strong仍是copy属性的对象,其指向的地址都是同一个,即为string指向的地址。若是咱们换做MRC环境,打印string的引用计数的话,会看到其引用计数值是3,即strong操做和copy操做都使原字符串对象的引用计数值加了1。orm
接下来,咱们把string由不可变改成可变对象,看看会是什么结果。对象
NSMutableString *string = [NSMutableString stringWithFormat:@"abc"];
其输出结果是:内存
origin string: 0x7ff5f2e33c90, 0x7fff59937a48 strong string: 0x7ff5f2e33c90, 0x7ff5f2e2aec8 copy string: 0x7ff5f2e2aee0, 0x7ff5f2e2aed0
能够发现,此时copy属性字符串已再也不指向string字符串对象,而是深拷贝了string字符串,并让_copyedString对象指向这个字符串。在MRC环境下,打印二者的引用计数,能够看到string对象的引用计数是2,而_copyedString对象的引用计数是1。字符串
此时,咱们若是去修改string字符串的话,能够看到:由于_strongString与string是指向同一对象,因此_strongString的值也会跟随着改变(须要注意的是,此时_strongString的类型其实是NSMutableString,而不是NSString);而_copyedString是指向另外一个对象的,因此并不会改变。string
结论
因为NSMutableString是NSString的子类,因此一个NSString指针能够指向NSMutableString对象,让咱们的strongString指针指向一个可变字符串是OK的。
而上面的例子能够看出,当源字符串是NSString时,因为字符串是不可变的,因此,无论是strong仍是copy属性的对象,都是指向源对象,copy操做只是作了次浅拷贝。
当源字符串是NSMutableString时,strong属性只是增长了源字符串的引用计数,而copy属性则是对源字符串作了次深拷贝,产生一个新的对象,且copy属性对象指向这个新的对象。另外须要注意的是,这个copy属性对象的类型始终是NSString,而不是NSMutableString,所以其是不可变的。
这里还有一个性能问题,即在源字符串是NSMutableString,strong是单纯的增长对象的引用计数,而copy操做是执行了一次深拷贝,因此性能上会有所差别。而若是源字符串是NSString时,则没有这个问题。
因此,在声明NSString属性时,究竟是选择strong仍是copy,能够根据实际状况来定。不过,通常咱们将对象声明为NSString时,都不但愿它改变,因此大多数状况下,咱们建议用copy,以避免因可变字符串的修改致使的一些非预期问题。