在iOS中,string是用strong修饰还是用copy修饰?它们有什么区别呢?本文主要就来讨论这两个问题,在此之前,我们需要知道两个术语,浅拷贝和深拷贝
浅拷贝:指对内存地址的复制,让目标对象指针和源对象指向同一片内存空间,当内存销毁的时候,指向这片内存的指针需要赋值,要不然会成为野指针
深拷贝:指对对象具体内容复制,重新分配对象的内存地址,拷贝结束之后,两个对象虽然值是相同的,但是内存地址不一样,两个对象也互不影响,互不干涉
上代码,测试一下
NSString *str = @"test";
NSString *copyStr = [str copy];
NSMutableString *mutStr = [str mutableCopy];
NSLog(@"指针地址:str:%p--copyStr:%p--mutStr:%p",&str,©Str,&mutStr);
NSLog(@"内存地址:str:%p--copyStr:%p--mutStr:%p",str,copyStr,mutStr);
运行结果:
指针地址:str:0x16fb31678--copyStr:0x16fb31670--mutStr:0x16fb31668
内存地址:str:0x1002d4080--copyStr:0x1002d4080--mutStr:0x1c024af80
可以看出:copy实现了一次浅拷贝,mutableCopy实现了一次深拷贝
实际上,对于copy和mutableCopy我们可以得出下表的结论
理解了copy作用,我们就不难理解属性中的copy和strong了,实际上在属性中copy比strong多了一步,即在setter方法中
- (void)setName:(id)name{
_name = [name copy];
}
举个例子:假设有这样一段代码
@property(copy)id obj;
self.obj = object;
此时obj是什么呢?有下面两种情况:
1. object是不可变对象,将会把object浅拷贝一次,赋值给obj
2. object是可变对象,将会把object深拷贝一次,赋值给obj
如果obj是用strong修饰的,就没有拷贝一说了,将会直接把object赋值给obj
在内存计数方面
strong 会使object引用计数+1,obj的引用计数为1
copy 如果object是不可变对象,object引用计数+1,obj的引用计数为1
如果object是可变对象,会将object深拷贝一份,object的引用计数不会变,obj的引用计数为1
综上所述,我们可以得出以下结论
-
当属性本身是可变对象时
此时只能用strong修饰,因为如下图,下图中,name属性经过setter时,得到的永远是不可变对象,当调用可变方法时,就会崩溃
-
当属性的赋值来源是可变对象时,如下图,看日志输出,发现当使用strong时,来源发生改变,属性值会跟着发生改变,当实用copy时,来源发生改变,属性不会跟着变
-
当属性的赋值来源是不可变对象时,如下图,发现strong和copy并没有什么区别
所以我们在选用修饰词时,我们要根据,属性本身是否可变,对属性赋值的来源是否可变,属性是否需要跟随来源的变化而变化等情况来选用属性的修饰词,不过,在实际开发中,大多数情况都是用copy
网友评论