首页 > 代码库 > 关于copyWithZone 实现拷贝
关于copyWithZone 实现拷贝
最近修复一bug ,进而窥见了copyWithZone(NSZone *)zone
该bug 场景是这样的
A 界面展示 一些地址列表,每行对应一个addressModel. 选中行
进入 B界面 展示 三行地址详情,分别是别名(如,公司),地址名(如,中关村XX). 其他(。。。) 选中B界面 地址名(中关村XX)
进入 C 界面 使用TextFied 输入并 搜索地址,
A 进入 B 进入 C 都是在界面跳转时 传递了同一个 addressModel.
C界面 搜索并选中地址后 回到 B 界面中,自然显示最新的选中结果(修改了同一个mode,大多数情况下,我们实现传递对象OC 是 用指针,*obj。). 需要在B 界面中 保持地址信息(B 就是编辑地址的界面,如删除,修改),回到A 界面 显示最新的修改结果。
但是在B 中修改了 地址信息 没有保持 直接返回 A 界面。这时 A中列表没有刷新,但实际上A界面内存中 该行对应Model 已经修改为B 界面中没有保持 的结果。 重复进入B 界面 ,傻眼了,显示了没有保持的 错误地址信息。
该bug 有不同解决思路。但本质应该是这样的。 A 中只需要给B 一个拷贝的对象,B 去修改或 不修改 在没有保存 同步到服务器 之前。返回A 没有任何影响。(B 中仅仅是个 备份)。
So,下面进入正题。如何 重写 copyWithZone(NSZone *)zone 实现 拷贝或 深拷贝。
首先,你要让自定义类实现NSCopying 或 NSMutableCopying 对应的是可变对象 和 非可变对象copy 协议。
如
CustomMode:NSObject<NSCopying>{
NSString * a;
int c;
}
……..
如果你的父类没有实现<NSCopying>,重写
-(id)copyWithZone(NSZone *)zone{
CustomMode *custom = [[[self class] copyWithZone:zone] init];
Custom ->_a = [_a copyWithZone:zone];
Custom -> _c = _c;//不是对象的 直接赋值
Return custom;
}实现深拷贝。在ARC 下。
如果你的父类实现了<NSCopying>,并重写了
-(id)copyWithZone(NSZone *)zone
CustomSuper:NSObject<NSCoping>
-(id)copyWithZone(NSZone *)zone{
CustomSuper *custom = [[[self class] copyWithZone:zone] init];
Return custom;
}
CustomMode:CustomSuper
-(id)copyWithZone(NSZone *)zone{
CustomModel *custom = [super copyWithZone:zone];
….
Return custom;
}
否则 直接向Custom 对象发copy 消息会蹦。
以为大功告成,但撇了一眼这篇文章 就不淡定了。
http://robnapier.net/implementing-nscopying
结论是。Objc_object 是一个结构体的实例。我们可以让所有的实例变量的快速内存拷贝为当前类。该结构的其余部分可能已被初始化为NULL如常。如果这听起来很复杂,应该是简单,只需调用class_getInstanceSize()为你的父类。添加它为self 去得到你第一个实例偏移。和memcpy()为您class_getInstanceSize()减去你的超类的字节数。然后,你可以清理你自己的保留计数不搞砸了你的子类。更妙的是,多个子类可以使用这个快速复制,而不会影响对方,相比NSCopyObject(),它只能通过顶层类的使用。
比如父类中实现 子类的深拷贝:
- (id)copyWithZone:(NSZone *)zone { id copyInstance = [[[self class] allocWithZone:zone] init]; size_t instanceSize = class_getInstanceSize([self class]); memcpy((__bridge voidvoid *)(copyInstance), (__bridge const voidvoid *)(self), instanceSize); return copyInstance; }
参见:
实现NSCopying(或NSCopyObject()是有害的)
http://robnapier.net/implementing-nscopying
http://blog.csdn.net/garychow520/article/details/20548383
http://stackoverflow.com/questions/12572999/what-is-the-operator-doing-in-copywithzone?rq=1
http://stackoverflow.com/questions/4089238/implementing-nscopying
关于copyWithZone 实现拷贝