如何在目标c中复制对象

ben*_*ben 110 copy objective-c

我需要深度复制具有自己的对象的自定义对象.我一直在阅读,并对如何继承NSCopying以及如何使用NSCopyObject感到困惑.有人可以帮帮我吗?谢谢阅读!

Ada*_*ght 189

与引用类型一样,有两种"复制"概念.我相信你知道他们,但是为了完整.

  1. 按位复制.在这里,我们只是将内存位复制一下 - 这就是NSCopyObject的作用.几乎总是,这不是你想要的.对象具有内部状态,其他对象等,并且经常假设它们是唯一持有对该数据的引用的对象.按位副本打破了这个假设.
  2. 深刻的逻辑副本.在这里,我们制作了一个对象的副本,但实际上没有一点一点地做 - 我们想要一个对所有意图和目的行为相同的对象,但不是(必然)原始的内存相同的克隆 - Objective C手册将这个对象称为"功能独立"的原始对象.因为制作这些"智能"副本的机制因类而异,我们要求对象本身执行它们.这是NSCopying协议.

你想要后者.如果这是您自己的对象之一,则只需采用协议NSCopying并实现 - (id)copyWithZone:(NSZone*)区域.你可以自由地做任何你想做的事情; 虽然这个想法是你自己制作一个真实的副本并将其归还.您可以在所有字段上调用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;
}
Run Code Online (Sandbox Code Playgroud)

  • @bobobobo:不,Objective-C内存管理的基本规则是:如果使用名称以"alloc"或"new"开头或包含"copy"的方法创建对象,则获取对象的所有权.`copyWithZone:`符合此条件,因此必须返回保留计数为+1的对象. (30认同)
  • 好吧,在现代基于OS X的运行时中,区域实际上是未使用的(即我认为它们实际上从未使用过).但是,你可以调用`allocWithZone`. (3认同)
  • @Adam 既然区域已传入,是否有理由使用“alloc”而不是“allocWithZone:”? (2认同)

Saq*_*aud 23

Apple文档说

copyWithZone:方法的子类版本应该首先将消息发送到super,以合并其实现,除非子类直接从NSObject下降.

添加到现有答案

@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;
}
Run Code Online (Sandbox Code Playgroud)

  • 我收到一个错误:`'NSObject'没有可见的@interface声明选择器'copyWithZone:'`.我想这只是在我们继承一些其他实现`copyWithZone`的自定义类时才需要的 (8认同)
  • 由于 YourClass 直接来自 NSObject 我认为这里没有必要 (2认同)
  • 好点,但它是一般规则,以防它的长级层次结构. (2认同)

Fel*_*rós 21

我不知道该代码和我的代码之间的区别,但我对该解决方案有问题,所以我再读一点,发现我们必须在返回之前设置对象.我的意思是:

#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;
}
Run Code Online (Sandbox Code Playgroud)

我添加了这个答案,因为我在这个问题上遇到了很多问题,我不知道为什么会这样.我不知道区别,但它对我有用,也许对其他人也有用:)