您的位置:首页 > 运维架构

copy 自定义对象

2017-07-12 00:00 120 查看
要向让我们自己创建的对象调用copy 方法,( [p copy] ) 前提条件是:

1> 遵守NSCopying协议 (本质上就是方便程序员编写代码时候,有快捷提示)
2> 实现 - (id)copyWithZone:(NSZone *)zone

copy方法, 最终都会调用copyWithZone方法

mutablecopy方法,最终都会调用mutableCopyWithZone方法

有一个模型对象Person

@interface Person : NSObject<NSCopying,NSMutableCopying>

@property(nonatomic,copy)NSString *name;
@property(nonatomic,assign)NSInteger age;

@end


遵守NSCopying协议 ,重写Person 的 copyWithZone方法 和 mutableCopyWithZone copy操作一个对象,复制给一个新的对象。

- (id)copyWithZone:(NSZone *)zone
{
// 1> 实例化对象,self 是对象
// self.class能够保证继承的子类同样使用copy方法
Person *p = [[self.class alloc] init];
//Person * p = [[self.class allocWithZone:zone] init];

// 2> 给属性赋值,深拷贝一份属性[self.name copy]字符串的copy方法,赋给新对象,但是这里不需要因为属性是不可变字符串。
p.name = self.name;
p.age = self.age;

// 3> 返回新对象
return p;
}


验证:

- (void)viewDidLoad {
[super viewDidLoad];

Person *p = [Person new];

Person *p2 = [p copy];

NSLog(@"%@,%@", p, p2);

}

结果如下:两个对象地址不一样。哦了



上面的模型属性中不包含容器类对象,如果包含容器类对象,我们这样写的话,会导致容器本身是深拷贝了,但是容器里面盛放的对象并不是深拷贝。里面的对象依旧是浅拷贝。面对这种情况应该这样写:

有一个Person模型对象,其中有一个 NSArray属性

@interface Person : NSObject<NSCopying,NSMutableCopying>

@property(nonatomic,copy)NSString *name;
@property(nonatomic,assign)NSInteger age;
@property(nonatomic,strong)NSArray *arr;

@end

重写 Person 的 copyWithZone方法 和 mutableCopyWithZone ,注意:p.arr = 不能简单的赋值,需要调用initWithArray: copyItems: 方法,这个方法可以让数组实现深拷贝,但是仅限于数组中没有再嵌套容器类,如果数组中再嵌套容器类,这个方法就不行了,需要使用归档。

- (id)copyWithZone:(NSZone *)zone{

//实例化对象
//self.class能够保证继承的子类可以使用copy方法
Person * p = [[self.class alloc] init];

//给属性赋值
p.age = self.age;
p.name = self.name;

//这里要注意了,不能单纯的赋值,单纯的赋值,就是代表引用同一个数组,当一个数组中的元素改变了。copy的数组中也会改,所以要深copy一份数组
p.arr = [[NSArray alloc] initWithArray:self.arr copyItems:YES];

//返回新对象
return p;

}


另外需要注意:initWithArray: copyItem: 这个方法调用时,self.arr中的对象 必须要具有copy的能力,不然会崩溃的,所以我们要将数组中的元素实现copy的方法。

- (id)copyWithZone:(NSZone *)zone{

//实例化对象
//self.class能够保证继承的子类可以使用copy方法
pm * p = [[self.class alloc] init];

//给属性赋值
p.days = self.days;

//返回新对象
return p;

}

- (id)mutableCopyWithZone:(NSZone *)zone{

//实例化对象
//self.class能够保证继承的子类可以使用copy方法
pm * p = [[self.class alloc] init];

//给属性赋值
p.days = self.days;

//返回新对象
return p;

}


验证:

//创建数组
pm *pmm = [pm new];
pmm.days = @"one";
NSArray *array = [NSArray arrayWithObjects:pmm, nil];

//创建模型
Person *p = [Person new];
//给模型中的数组赋值
p.arr = array;

//copy模型
Person *p2 = [p copy];
//修改copy后的模型数组中对象的值
[[p2.arr lastObject] setDays:@"two"] ;

//打印结果
NSLog(@"%@", [[p.arr lastObject] days]);
NSLog(@"%@", [[p2.arr lastObject] days]);

结果如下:修改copy后的对象中的数组属性中的元素后, 原始的对象中的值并没有变,说明copy成功了。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: