objective-c 如何在Objective-C中复制对象
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/1459598/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How to copy an object in Objective-C
提问by ben
I need to deep copy a custom object that has objects of its own. I've been reading around and am a bit confused as to how to inherit NSCopying and how to use NSCopyObject.
我需要深度复制一个具有自己对象的自定义对象。我一直在阅读,对于如何继承 NSCopying 以及如何使用 NSCopyObject 感到有些困惑。
回答by Adam Wright
As always with reference types, there are two notions of "copy". I'm sure you know them, but for completeness.
与引用类型一样,“复制”有两个概念。我相信你知道他们,但为了完整性。
- A bitwise copy. In this, we just copy the memory bit for bit - this is what NSCopyObject does. Nearly always, it's not what you want. Objects have internal state, other objects, etc, and often make assumptions that they're the only ones holding references to that data. Bitwise copies break this assumption.
- A deep, logical copy. In this, we make a copy of the object, but without actually doing it bit by bit - we want an object that behaves the same for all intents and purposes, but isn't (necessarily) a memory-identical clone of the original - the Objective C manual calls such an object "functionally independent" from it's original. Because the mechanisms for making these "intelligent" copies varies from class to class, we ask the objects themselves to perform them. This is the NSCopying protocol.
- 按位复制。在这里,我们只是逐位复制内存 - 这就是 NSCopyObject 所做的。几乎总是,这不是您想要的。对象具有内部状态、其他对象等,并且经常假设它们是唯一持有对该数据的引用的对象。按位复制打破了这个假设。
- 一个深刻的、合乎逻辑的副本。在这里,我们制作了对象的副本,但实际上并没有一点一点地做——我们想要一个对象在所有意图和目的上的行为都相同,但不是(必然)原始内存相同的克隆—— Objective C 手册称这样的对象与其原始对象“功能独立”。因为制作这些“智能”副本的机制因类而异,所以我们要求对象本身执行它们。这是 NSCopying 协议。
You want the latter. If this is one of your own objects, you need simply adopt the protocol NSCopying and implement -(id)copyWithZone:(NSZone *)zone. You're free to do whatever you want; though the idea is you make a real copy of yourself and return it. You call copyWithZone on all your fields, to make a deep copy. A simple example is
你想要后者。如果这是您自己的对象之一,您只需采用 NSCopying 协议并实现 -(id)copyWithZone:(NSZone *)zone。你可以随心所欲;虽然这个想法是你制作自己的真实副本并将其归还。您在所有字段上调用 copyWithZone 以进行深层复制。一个简单的例子是
@interface YourClass : NSObject <NSCopying>
{
SomeOtherObject *obj;
}
// In the implementation
-(id)copyWithZone:(NSZone *)zone
{
// We'll ignore the zone for now
YourClass *another = [[YourClass alloc] init];
another.obj = [obj copyWithZone: zone];
return another;
}
回答by Saqib Saud
Apple documentation says
苹果文档说
A subclass version of the copyWithZone: method should send the message to super first, to incorporate its implementation, unless the subclass descends directly from NSObject.
copyWithZone: 方法的子类版本应该首先将消息发送到 super,以合并其实现,除非子类直接从 NSObject 继承。
to add to the existing answer
添加到现有答案
@interface YourClass : NSObject <NSCopying>
{
SomeOtherObject *obj;
}
// In the implementation
-(id)copyWithZone:(NSZone *)zone
{
YourClass *another = [super copyWithZone:zone];
another.obj = [obj copyWithZone: zone];
return another;
}
回答by Felipe Quirós
I don't know the difference between that code and mine, but I have problems with that solution, so I read a little bit more and found that we have to set the object before return it. I mean something like:
我不知道那个代码和我的有什么区别,但是我对那个解决方案有问题,所以我读了一点,发现我们必须在返回之前设置对象。我的意思是这样的:
#import <Foundation/Foundation.h>
@interface YourObject : NSObject <NSCopying>
@property (strong, nonatomic) NSString *name;
@property (strong, nonatomic) NSString *line;
@property (strong, nonatomic) NSMutableString *tags;
@property (strong, nonatomic) NSString *htmlSource;
@property (strong, nonatomic) NSMutableString *obj;
-(id) copyWithZone: (NSZone *) zone;
@end
@implementation YourObject
-(id) copyWithZone: (NSZone *) zone
{
YourObject *copy = [[YourObject allocWithZone: zone] init];
[copy setNombre: self.name];
[copy setLinea: self.line];
[copy setTags: self.tags];
[copy setHtmlSource: self.htmlSource];
return copy;
}
I added this answer because I have a lot of problems with this issue and I have no clue about why is it happening. I don't know the difference, but it's working for me and maybe it can be useful for others too : )
我添加了这个答案是因为我在这个问题上有很多问题,我不知道为什么会这样。我不知道有什么区别,但它对我有用,也许对其他人也有用:)
回答by Szuwar_Jr
another.obj = [obj copyWithZone: zone];
I think, that this line causes memory leak, because you access to objthrough property which is (I assume) declared as retain. So, retain countwill be increased by property and copyWithZone.
我认为,这一行会导致内存泄漏,因为您可以访问obj(我假设)声明为retain. 因此,保留计数将通过属性和 增加copyWithZone。
I believe it should be:
我认为应该是:
another.obj = [[obj copyWithZone: zone] autorelease];
or:
或者:
SomeOtherObject *temp = [obj copyWithZone: zone];
another.obj = temp;
[temp release];
回答by Alex Nolasco
There is also the use of the -> operator for copying. For Example:
还可以使用 -> 运算符进行复制。例如:
-(id)copyWithZone:(NSZone*)zone
{
MYClass* copy = [MYClass new];
copy->_property1 = self->_property1;
...
copy->_propertyN = self->_propertyN;
return copy;
}
The reasoning here is the resulting copied object should reflect the state of the original object. The "." operator could introduce side effects as this one calls getters which in turn may contain logic.
这里的推理是生成的复制对象应该反映原始对象的状态。这 ”。” 运算符可能会引入副作用,因为这会调用 getter,而 getter 又可能包含逻辑。

