复制对象
一、copy和mutableCopy方法
1、简介:Foundation类实现了名为copy和mutableCopy的方法,可以使用这些方法创建对象的副本。通过实现一个符合<NSCopying>(不可变的)协议 或<NSMutableCopying>(可变的)(用于制作副本)的方法来完成此任务。
注:产生一个对象的可变副本并不要求被复制的文件本身是可变的;这种情况同样适用于不可变副本,可以创建可变对象的不可变副本。
2、复制对象副本与使用赋值语句的区别:
赋值的结果仅仅是将对象的地址复制到另一对象中。操作结束时,两个变量都指向内存中的同一地址。而使用copy与mutableCopy复制对象副本的在内存中创建了一个新的副本,并复制了它的所有元素。
3、使用方法,如:
NSMutableArray *dataArray = [NSMutableArray arrayWithObjects: @”One”, @”Two”, nil];
NSMutableArray *dataArray2;
dataArray2 = [dataArray mutableCopy];
二、浅复制与深复制
1、浅复制:浅复制仅复制对象本身。
2、深复制:在浅复制的基础上,连同引用的元素对象也一起复制。
3、浅复制与深复制的区别:
1>、当复制的对象中的元素为完全值类型时没有区别。
2>、当复制的对象中的元素为引用对象时;浅复制复制对象时,在内存中为新的对象分配了空间,并且将单个元素复制到新的数组中。然而将原始数组中的每个元素复制到新位置意味:仅将引用从一个对象元素复制到另一个对象元素。也就是对象中的元素都指向内存中的同一个字符串,与将一个对象赋值给另一个对象无区别。而深复制,在复制对象时为对象中的每个元素创建完全不同的副本。
4、注:
1>、此情况使用浅复制不能随便删除对象中的元素,否则会造成另一对象引用元素失效。
2>、系统默认执行浅复制。
三、实现<NSCopying>协议
1、要实现使用自己的类进行复制,必须根据<NSCopying>协议实现其中一两个方法。
2、interface指令应该如下所示:
@interface Fraction: NSObject <NSCopying>;
3、注意:
1>、必须考虑一个事实:超类可能已经实现了它自己的复制策略。
2>、实现<NSCopying>协议时,类必须实现copyWithZone: 方法来响应cipy消息。(这条消息仅将一条带有nil参数的copyWithZone: 消息发送给你的类)。
3>、如果你的类可以产生子类,那么cipyWithZone: 方法将被继承。
4>、如果编写一个类的copyWithZone: 方法,而该类的超类敢实现了<NSCopying>协议,那么应该先调用超类的copy方法以复制继承来的实例变量,然后加入自 己的代码以复制想要添加该类中的任何附加的实例变量。
四、用赋值方法和取值方法复制对象
1、只要实现赋值方法或取值方法,都应该考虑实例变量中存储的内容,要检索的内容以及是否需要保护这些值。
例:考虑使用setName: 方法来设置AddressCard对象的名称时:
[newCard setname: newName];
假设newName是一个字符串对象,它包含新地址卡片的名称。假定在赋值方法全程内,你中是简单地将参数赋值给相应的实例变量:
-(void) setName: (NSString *) theName
{
name = theName;
}
为了避免更改程序的newName中包含的一些字符,而无意间对程序产生影响。通过使用alloc方法来创建新的string对象,然后使用inteWithString: 函数将该方法提供的参数值赋给它,可以实现在赋值对象内产生副本。
2、还可以编写如下的setName: 方法来使用copy:
-(void) setName: (NSString *) theName
{
name = [theName copy];
}
当然,要使赋值方法全程的内存管理友好一些,首先应该自动释放旧的值,如下所示:
-(void) setName: (NSString *) theName
{
[name autorelease];
name = [theName copy];
}
3、如果在属性声明中为实例变量指定了copy属性,那么合并后的方法会使用类的copyyyif(你编写的copy方法或继承的copy方法)。所以下列property声明
@property (nonatomic, copy) NSString *name;
会生成一个合并的方法,其行为类似于
-(void) setName: (NSString *)theName
{
If(theName != name)
{
[name release];
Name = [theName copy];
}
}