在OC中,对象、block存在深浅拷贝,其拷贝的在不同的情况下也不相同,以下就是针对对不同情况下深浅拷贝的详解:
retain :始终是浅拷贝,引用计数每次加1,返回对象是否可变跟对象是否可变完全一致。
copy :对于可变对象为深拷贝,引用计数不变,对于不可变对象是浅拷贝,引用计数每次加1.始终返回一个不可变对象。
mutableCopy:对于任何对象都是深拷贝,引用计数不变,始终返回一个可变对象。
总结:对于系统类的对象,除了NSString、NSNumber、NSArray、NSDictionary的copy是浅拷贝,其他情况都是深拷贝。而且不管被拷贝的对象是否为可变的,copy后的对象都是不可变的,mutableCopy之后的对象都是可变的。对于我们手动创建的对象,其是可变对象,所有其copy也是深拷贝,mutableCopy也是深拷贝,这两种拷贝返回的对象都是可变的。
下面是针对不同情况的详细说明:
(1)系统容器类对象(NSArray、NSDictionary)
1.NSArray and NSMutableArray
NSArray
**************************************************
NSArray *arr1 = [[NSArray alloc]initWithObjects:@"zhangsan",@"lisi",@"wangwu" , nil];
NSArray *arr2 = [arr1 copy];
NSMutableArray *arr3 = [arr1 mutableCopy];
NSLog(@"<%p>,<%p>,<%p>",arr1,arr2,arr3);
for (NSString *str in arr1) {
NSLog(@"str1=%p:%@",str,str);
}
for (NSString *str in arr2) {
NSLog(@"str2=%p:%@",str,str);
}
for (NSString *str in arr3) {
NSLog(@"str3=%p:%@",str,str);
}
//从结果来说,可以看出,NSArray copy是浅拷贝,mutableCopy是深拷贝,而数组里面的内容都是浅拷贝
NSMutableArray
************************************************************************
NSMutableArray *arr1 = [[NSMutableArray alloc]initWithObjects:@"zhangsan",@"lisi",@"wangwu" , nil];
NSMutableArray *arr2 = [arr1 copy];
NSMutableArray *arr3 = [arr1 mutableCopy];
NSLog(@"<%p>,<%p>,<%p>",arr1,arr2,arr3);
for (NSString *str in arr1) {
NSLog(@"str1=%p:%@",str,str);
}
for (NSString *str in arr2) {
NSLog(@"str2=%p:%@",str,str);
}
for (NSString *str in arr3) {
NSLog(@"str3=%p:%@",str,str);
}
//从结果来说,NSMutableArray 的copy、mutableCopy都是深拷贝。而数组里面的内容是浅拷贝。
小结:除了NSArray 的copy是浅拷贝,其他情况都是深拷贝,而且Array内的元素都是浅拷贝。
2.NSDictionary and NDMutableDictionary
<span style="white-space:pre"> </span> NSDictionary
*************************************************************
NSDictionary *dic1 = [[NSDictionary alloc]initWithObjectsAndKeys:@"zhangsan",@"张三",@"lisi",@"李四",@"wangwu",@"王五",nil];
NSDictionary *dic2 = [dic1 copy];
NSMutableDictionary *dic3 = [dic1 mutableCopy];
NSLog(@"<%p>,<%p>,<%p>",dic1,dic2,dic3);
for (NSString *str in dic1) {
NSLog(@"str1=%p:%@",str,str);
}//打印dic1
for (NSString *str in dic2) {
NSLog(@"str2=%p:%@",str,str);
}//打印dic2
for (NSString *str in dic3) {
NSLog(@"str3=%p:%@",str,str);
}//打印dic3
从结果可以看出,NSDictionary 的copy是浅拷贝,mutableCopy是深拷贝,其中的数组元素也是浅拷贝
*********************************************************************
NSMutableDictionary
NSMutableDictionary *dic4 = [[NSMutableDictionary alloc]initWithObjectsAndKeys:@"zhangsan",@"张三",@"lisi",@"李四",@"wangwu",@"王五",nil];
[dic4 setObject:@"wangmazi" forKey:@"王麻子"];
NSMutableDictionary *dic5 = [dic4 copy];
NSMutableDictionary *dic6 = [dic4 mutableCopy];
NSLog(@"<%p>,<%p>,<%p>",dic4,dic5,dic6);
for (NSString *str in dic4) {
NSLog(@"str4=%p:%@",str,str);
}//打印dic4
for (NSString *str in dic5) {
NSLog(@"str5=%p:%@",str,str);
}//打印dic5
for (NSString *str in dic6) {
NSLog(@"str6=%p:%@",str,str);
}//打印dic6
从结果来看,NSMutableDictionary的copy、mutableCopy拷贝都是深拷贝,其内容也都是浅拷贝。
小结: 除了NSDictionary的copy是浅拷贝,其他都是深拷贝,字典内部的元素也是浅拷贝。
(2)系统非容器类对象 (NSString、NSNumber)
1.NSString and NSMutablString
NSString
****************************************************************
NSString *str = [[NSString alloc] initWithFormat:@"hello_%d",1];
//1.NSString 使用copy后的对象是不可变的。相当于浅拷贝
NSString *seceondStr = [str copy];
NSLog(@"secondStr:%@",seceondStr);
//2.NSString 使用MutableCopy 之后 的对象是可变的,相当于深拷贝
NSMutableString *thirdStr = [str mutableCopy];
[thirdStr appendString:@"333"];
NSLog(@"thirdStr:%@",thirdStr);
<pre name="code" class="objc">**************************<span style="font-family: Arial, Helvetica, sans-serif;"> NSMutableString****************************************************************</span>
NSMutableString *str = [[NSMutableString alloc]initWithString:@"hello"]; //3.NSMutableString 使用copy之后的对象是不可改变的,相当于深拷贝, NSMutableString *secondStr = [str copy]; //[secondStr appendString:@"222"];不可增加,即不可变 NSLog(@"secondStr:%@",secondStr); //4,NSMutableString 使用 MutableCopy之后的对象是可改变的。相当于深拷贝 NSMutableString *thirdStr = [str mutableCopy]; [thirdStr appendString:@"3333"]; NSLog(@"thirdStr : %@",thirdStr); 小结:除了NSString的copy是浅拷贝,其他都是深拷贝
2.NSNumber的结果与NSString类似,在此省略
(3)手动创建的类对象
对于我们手动创建的类,我们如果要想实现copy,必须显示的采用OC提供的NSCoping、NSMutableCoping协议,实现这两个协议的方法copyWithZone:(NSZone )zone 和mutableCopyWithZone:(NSZone )zone.
例子:
//声明一个Person类,继承与NSObject类,并显示的采用NSCopying,NSMutableCopying协议
@interface Person : NSObject <NSCopying,NSMutableCopying>
@property (nonatomic,copy)NSString *name;//姓名
@property (copy,nonatomic)NSString *address;//地址
@end
//类的实现,
@implementation Person
- (NSString *)description
{
return [NSString stringWithFormat:@"person's info is :name = %@,address= %@", self.name,self.address];
}
//实现协议NSCopying的方法copyWithZone:(NSZone *)zone
- (id)copyWithZone:(NSZone *)zone{
Person *temp = [[[self class] allocWithZone:zone]init];
temp.name = _name;
temp.address = _address;
return temp;
}
//实现协议NSMutableCopying的方法mutableCopyWithZone:(NSZone *)zone
- (id) mutableCopyWithZone:(NSZone *)zone{
Person *mTemp = [[Person allocWithZone:zone]init];
mTemp.name = [_name copy];
mTemp.address = [_address copy];
return mTemp;
}
@end
在main方法中:
//创建一个类对象,并初始化其信息
Person *person = [[Person alloc]init];
person.name = @"zhangsan";
person.address = @"henan";
NSLog(@"count:%lu",person.retainCount);
NSLog(@"<%p>:<%p>:<%p>%@",person,person.name,person.address,person);
//实现copy对象,并打印其信息
Person *cPerson = [person copy];
cPerson.name = @"lisi";
cPerson.address =@"hebei";
NSLog(@"count:%lu",person.retainCount);
NSLog(@"<%p>:<%p>:<%p>%@",cPerson,cPerson.name,cPerson.address,cPerson);
//实现mutableCopy对象,并打印其信息
Person *mcPerson = [person mutableCopy];
mcPerson.name = @"wnagwu";
mcPerson.address = @"beijing";
NSLog(@"count:%lu",person.retainCount);
NSLog(@"<%p>:<%p>:<%p>%@",mcPerson,mcPerson.name,mcPerson.address,mcPerson);
结果为:
-------------------before copy and mutableCopy------------------
person'retainCount:1
<0x1001065a0>:<0x100002350>:<0x100002370>person's info is :name = zhangsan,address= henan
-------------------after copy------------------
person'retainCount:1
<0x100500110>:<0x1000023d0>:<0x1000023f0>person's info is :name = lisi,address= hebei
-------------------after mutableCopy------------------
person'retainCount:1
<0x100107060>:<0x100002410>:<0x100002430>person's info is :name = wnagwu,address= beijing
从结果可以看出:person对象是一个可变对象,其调用copy、mutableCopy方法之后返回的对象都是可变的,而且都是深拷贝。