1、复制对象的基本概念
复制对象就是复制一个对象作为副本,它会开辟一块新的内存(堆内存)来存储副本对象,就像复制文件一样。即源对象和副本对象是两块不同的内存区域。
NSMutableArray *muArray = [NSMutableArrayarrayWithObjects:@"zhangsan",@"lisi",nil];
//用copy复制了一份不可修改的副本
NSArray *array2 = [muArray copy];
此时array2是不可修改的,它是不可变的。
mutableCopy方法用于复制对象的可变副本。即,用mutableCopy复制得到的对象是可变的。一个不可变对象使用mutableCopy方法赋值得到的对象也是可变的。
例如:一个不可变数组使用mutable方法进行复制,会得到一个可变的数组
NSArray *array1 =@[@"one",@"two",@"three"];
//用mutableCopy复制了array1的一份可修改的副本
NSMutableArray *array = [array1 mutableCopy];
NSLog(@"%@",array);
[array addObject:@"four"];
NSLog(@"%@",array);
结果为:
NSMutableArray *muArray = [NSMutableArrayarrayWithObjects:@"zhangsan",@"lisi",nil];
NSMutableArray *muArray1 = [muArray retain];
//因为retain是指针拷贝,所以muArray与muArray1的指针相同
//muArray1 移除一个元素,muArray也会移除一个元素
[muArray1 removeObject:@"lisi"];
NSLog(@"%@",muArray);
NSLog(@"%@",muArray1);
4、实现自定义对象的复制功能
首先定义一个类:
@interface Person : NSObject
@property (nonatomic,retain)NSMutableString *userName;
@property (nonatomic,assign)int age;
@end
若直接对自定义对象进行拷贝
Person *person = [[Personalloc] init];
person.userName = [NSMutableStringstringWithString:@"张三"];
person.age = 19;
Person *copyPerson = [person copy];
上述结果表明,直接对自定义对象进行拷贝,程序将会崩溃。
那么,要如何对自定义对象进行拷贝呢?
当程序调用对象的copy方法来复制对象时,程序底层需要调用copyWithZone方法来完成实际的复制工作,copy返回的实际上就是copyWithZone方法的返回值。
当程序调用mutableCopy方法来复制对象时,程序底层需要调用mutableCopyWithZone方法来完成实际的复制工作,mutableCopy实际上就是返回mutableCopyWithZone方法的返回值。
为了实现自定义对象的拷贝,通常需要类实现NSCopying协议和copyWithZone方法,或者NSMutableCopy协议和mutableCopyWithZone方法。
@interface Person :NSObject<NSCopying>
@property (nonatomic,retain)NSMutableString *userName;
@property (nonatomic,assign)int age;
@end
@implementation Person
-(id)copyWithZone:(NSZone *)zone{
Person *person = [[[selfclass] allocWithZone:zone]init];
person.userName =_userName;
person.age = _age;
return person;
}
@endPerson *person = [[Personalloc] init];
person.userName = [NSMutableStringstringWithString:@"张三"];
person.age = 19;
Person *copyPerson = [person copy];
NSLog(@"copyPerson的userName:%@",copyPerson.userName);
NSLog(@"person的userName:%@",person.userName);
5、浅拷贝和深拷贝
浅拷贝(shallow copy),当对象的属性是指针变量时,如果程序只是复制该指针的地址,而不是真正复制指针所指向的对象,这种方式就称为浅拷贝
深拷贝(deep copy),深拷贝不仅会复制对象的本身,而且会递归复制每个指针类型的属性,直到两个对象没有任何的公用部分为止。
继续以上述例子中的Person类为例:
若改变person属性userName的值,会发生什么呢?
Person *person = [[Personalloc] init];
person.userName = [NSMutableStringstringWithString:@"张三"];
person.age = 19;
Person *copyPerson = [person copy];
//给person对象中的username属性拼接一个字符串@"11111"
[person.userName appendString:@"11111"];
NSLog(@"copyPerson的userName:%@",copyPerson.userName);
NSLog(@"person的userName:%@",person.userName);
-(id)copyWithZone:(NSZone *)zone{
Person *person = [[[selfclass] allocWithZone:zone]init];
person.userName = [_userNamecopy];//对对象属性进行拷贝
person.age = _age;
return person;
}
执行结果变为:
这样person和copyPerson就完全没有共同部分,因此实现了深拷贝。