OC中的复制
什么是复制?
复制是一种拷贝,无论是对对象指针的拷贝(浅拷贝),还是对对象内容的拷贝(深拷贝),其最终实现的是对对象的拷贝。
复制的条件?
<NSCoping>protocol
凡是遵循NSCoping协议的对象都可以进行copy。
NSCoping协议中声明:
- (id)copyWithZone:(NSZone *)zone;
- (id)copyWithZone:(NSZone *)zone{
NSString *name=[self.name copy];//这里假如self.name是可变字符串的话,那么执行的就是深复制,否则执行的是浅复制(原因见下面分析)。
Person *p=[[Person alloc] initWithName:name age:self.age];//将以前的值拷贝过来,返回到一个新的空间
- }
什么时候使用复制?
当我们需要获取一个容器的内容的时候,我们可以采取复制方法。至于是通过指针来访问拷贝前对象的内容(浅拷贝)还是通过指针来访问新空间的内容(深拷贝),取决于被拷贝对象的允许度以及我们采取的方法力度。
为什么要用复制?
深复制可以让我们在不破坏之前对象内容的情况下,在新空间获得跟之前等值的内容,并且可以对新空间的内容进行我们必要的处理。
浅复制我们如果改变指针指向内容的时候,就容易变动之前对象内容,不安全。
复制的方法与特点?
苹果官网解析图
Shallowcopying:
对象A 指针textColor指向textColor的内容,经过shallow copy后,对象B中指针也指向了textColor。
在浅拷贝中,由于同一个对象增加了一个指针,因此retain count增加1.
Deep copying:
可以看出是重新开辟了一个空间来盛装textColor指向的内容,同时用一个新的指针指向这个新的内容。
分类说明:
(1)对于字符串的拷贝
NSString
NSString *str3=[NSString stringWithFormat:@"zhangsan"];
[str3 retain];//
NSLog(@"%lu",[str3 retainCount]);//1
NSString *str4=[str3 copy];//2
NSLog(@"%lu %p %p",[str3 retainCount],str3,str4);//两个地址相同,说明实现的是浅拷贝,计数增加1.
经过检测,无论接收数组是可变的还是不可变的,对于不可变字符串的拷贝都是浅拷贝。
MutableString
NSMutableString *str1=[NSMutableString stringWithString:@"wangliang"];
NSLog(@"%lu",[str1 retainCount]);
// NSLog(@"%lu",[str5 retainCount]);//这里str5没有开辟空间,因此不存在计数。
NSMutableString *str2=[str1 copy];//拷贝
NSLog(@"%lu %lu",[str1 retainCount],[str2 retainCount]);//1 1
NSLog(@"%@ %p %p",str2,str2,str1);//wangliang地址相同
[str1 release];//这里str1本身的计数为1,如果再进行release就会dealloc,出现crash。
经过测试,无论是用可变字符串还是不可变来接收拷贝返回值,可变字符串拷贝都是深拷贝,拷贝后retaincount数值不变,地址不一样。
(2)对于数组的拷贝
NSArray
NSArray *arr=@[@"zhangsan",@"lisi",@"wangwu"];
NSArray *arr1=[arr copy];//此时arr1的计数也为2
NSLog(@"%lu",[arr
retainCount]);//2
NSLog(@"%p %@ %p %@",arr,arr,arr1,arr);//打印出来的两个数组的内容相同,说明经过测试:已经实现了拷贝,但是两个数组的指针也相同,说明不可变数组实现的只是浅拷贝。
NSutableArray
NSMutableArray *arrM=[[NSMutableArray alloc] initWithObjects:@"zhangsan",@"lisi",@"wangwu", nil];
NSArray *arrm=[arrM copy];
NSLog(@"%p %p",arrM,arrm);
经过测试,无论是用可变数组还是不可变数组来接收拷贝返回值,可变数组拷贝都是深拷贝,拷贝后retaincount数值不变,地址不一样。
总结:
对于不可变容器的拷贝,只能采用retain方式进行拷贝,也就是对不可变容器进行指针的拷贝。对于可变容器的拷贝,进行的都是深拷贝,拷贝的过程是先创建一个空间,然后将拷贝值放入创建的新空间中。