关于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

时间: 2024-07-31 11:35:27

关于copyWithZone 实现拷贝的相关文章

iOS 集合的深复制与浅复制

概念 对象拷贝有两种方式:浅复制和深复制.顾名思义,浅复制,并不拷贝对象本身,仅仅是拷贝指向对象的指针:深复制是直接拷贝整个对象内存到另一块内存中. 一图以蔽之 再简单些说:浅复制就是指针拷贝:深复制就是内容拷贝. 集合的浅复制 (shallow copy) 集合的浅复制有非常多种方法.当你进行浅复制时,会向原始的集合发送retain消息,引用计数加1,同时指针被拷贝到新的集合. 现在让我们看一些浅复制的例子: NSArray *shallowCopyArray = [someArray cop

深复制与浅复制

概念 对象拷贝有两种方式:浅复制和深复制.顾名思义,浅复制,并不拷贝对象本身,仅仅是拷贝指向对象的指针:深复制是直接拷贝整个对象内存到另一块内存中. 一图以蔽之 再简单些说:浅复制就是指针拷贝:深复制就是内容拷贝. 集合的浅复制 (shallow copy) 集合的浅复制有非常多种方法.当你进行浅复制时,会向原始的集合发送retain消息,引用计数加1,同时指针被拷贝到新的集合. 现在让我们看一些浅复制的例子: NSArray *shallowCopyArray = [someArray cop

OC基础(26)

集合对象的内存管理 Copy copy与内存管理 @property中的copy关键字 自定义的类实现copy操作 *:first-child { margin-top: 0 !important; } body > *:last-child { margin-bottom: 0 !important; } a { color: #4183C4; } a.absent { color: #cc0000; } a.anchor { display: block; padding-left: 30p

copy&amp;mutableCopy 浅拷贝(shallow copy)深拷贝 (deep copy)

本文来自 这里,原文作者微博MicroCai 概念 对象拷贝有两种方式:浅复制和深复制.顾名思义,浅复制,并不拷贝对象本身,仅仅是拷贝指向对象的指针:深复制是直接拷贝整个对象内存到另一块内存中. 一图以蔽之 再简单些说:浅复制就是指针拷贝:深复制就是内容拷贝. 集合的浅复制 (shallow copy) 集合的浅复制有非常多种方法.当你进行浅复制时,会向原始的集合发送retain消息,引用计数加1,同时指针被拷贝到新的集合. 现在让我们看一些浅复制的例子: NSArray *shallowCop

自定义的类实现copy操作

1.自定义类实现copy操作 让类遵守NSCopying协议 实现 copyWithZone:方法,在该方法中返回一个对象的副本即可. 在copyWithZone方法中,创建一个新的对象,并设置该对象的数据与现有对象一致, 并返回该对象. zone: 表示空间,分配对象是需要内存空间的,如果指定了zone,就可以指定 新建对象对应的内存空间.但是:zone是一个非常古老的技术,为了避免在堆中出现内存碎片而使用的.在今天的开发中,zone几乎可以忽略 无父类实现 - (id)copyWithZon

iOS深拷贝与浅拷贝

概念 对象拷贝有两种方式:浅复制和深复制.顾名思义,浅复制,并不拷贝对象本身,仅仅是拷贝指向对象的指针:深复制是直接拷贝整个对象内存到另一块内存中. 如图详解: 再简单些说:浅复制就是指针拷贝:深复制就是内容拷贝. 集合的浅拷贝 (shallow copy) 集合的浅复制有非常多种方法.当你进行浅复制时,会向原始的集合发送retain消息,引用计数加1,同时指针被拷贝到新的集合. 浅拷贝的例子: NSArray *shallowCopyArray = [someArray copyWithZon

OC蜕变最后一天

总结 编号 主题 内容 一 NSFileManager NSFileManager介绍/用法(常见的判断)/文件访问/文件操作 二 集合对象的内存管理 集合对象的内存管理/内存管理总结 三 *copy copy基本概念/使用/copy快速入门/内存管理 四 @Property中的copy关键字 @property中的copy的作用/@property内存管理策略选择 五 自定义类实现copy操作 自定义类实现copy操作 六 单例设计模式 单例模式概念/简单的单例模式实现 七 宏定义抽取单例 一

weak和拷贝

weak/拷贝 1. weak 只要没有strong指针指向对象,该对象就会被销毁 2. 拷贝 NSString和block用copy copy语法的作用 产生一个副本 修改了副本(源对象)并不会影响源对象(副本) 实现拷贝的方法 copy: 返回的是不可变副本 可变字符串调用copy生成不可变的副本 副本与源对象(不可变的)的地址相同 自定义对象用copy即可(副本与源对象的地址不同),如果用strong则副本与源对象地址一样 copy内部会调用copyWithZone方法 遵守NSCopyi

Objective-C:OC内部可变对象和不可变对象的深(复制)拷贝问题思考:

OC内部:可变对象和不可变对象的深(复制)拷贝问题思考: 不可变对象: 例如NSString对象,因为NSString对象是常量字符串,所以,不可以更改其内容,但是可以修改指向该字符串的指针指向.当对NSString对象做深拷贝时,如果是copy复制方式,其实就是浅复制,只是复制了同一个对象的指针:如果是mutableCopy复制方式,系统会分配一个新的内存空间用来存放复制出来的NSMutableString对象,此时地址是新的,内容是一样的,他们正在被不同的实例变量字符串指针指着. 可变对象: