实施copyWithZone时的最佳做法:

我正在尝试清理一些关于执行copyWithZone:事情copyWithZone: ,任何人都可以对以下内容进行评论…

 // 001: Crime is a subclass of NSObject. - (id)copyWithZone:(NSZone *)zone { Crime *newCrime = [[[self class] allocWithZone:zone] init]; if(newCrime) { [newCrime setMonth:[self month]]; [newCrime setCategory:[self category]]; [newCrime setCoordinate:[self coordinate]]; [newCrime setLocationName:[self locationName]]; [newCrime setTitle:[self title]]; [newCrime setSubtitle:[self subtitle]]; } return newCrime; } // 002: Crime is not a subclass of NSObject. - (id)copyWithZone:(NSZone *)zone { Crime *newCrime = [super copyWithZone:zone]; [newCrime setMonth:[self month]]; [newCrime setCategory:[self category]]; [newCrime setCoordinate:[self coordinate]]; [newCrime setLocationName:[self locationName]]; [newCrime setTitle:[self title]]; [newCrime setSubtitle:[self subtitle]]; return newCrime; } 

在001:

  1. 最好直接编写类名[[Crime allocWithZone:zone] init]还是应该使用[[[self Class] allocWithZone:zone] init]

  2. 可以使用[self month]来复制iVar,还是直接访问iVar,即_month

  1. 你应该总是使用[[self class] allocWithZone:zone]来确定你正在使用适当的类创build一个副本。 你给002的例子显示了原因:子类将调用[super copyWithZone:zone]并期望获得适当类的实例,而不是超类的实例。

  2. 我直接访问ivars,所以我不需要担心后面可能会添加到属性setter(例如,生成通知)的任何副作用。 请记住,子类可以自由地覆盖任何方法。 在你的例子中,你发送两个额外的信息每伊法尔。 我将执行如下:

码:

 - (id)copyWithZone:(NSZone *)zone { Crime *newCrime = [super copyWithZone:zone]; newCrime->_month = [_month copyWithZone:zone]; newCrime->_category = [_category copyWithZone:zone]; // etc... return newCrime; } 

当然,无论是复制ivars,保留它们,还是只分配它们,都应该反映这些设置者所做的事情。

使用SDK提供的对象的copyWithZone:方法的默认复制行为是“浅拷贝”。 这意味着如果你调用copyWithZone:NSString对象上,它将创build一个浅拷贝而不是深拷贝。 浅层和深层复制的区别在于:

一个对象的浅拷贝将只复制到原始数组的对象的引用,并将它们放入新的数组中。

深层复制将实际上复制包含在对象中的单个对象。 这是通过发送每个单独的对象copyWithZone:消息在您的自定义类方法中完成的。

INSHORT:为了获得浅拷贝,你可以对所有实例variables调用retainstrong 。 要获得深层副本,请调用copyWithZone:对自定义类copyWithZone:实现中的所有实例variables。 现在,您可以select。

这是我的模型。

 #import <Foundation/Foundation.h> @interface RSRFDAModel : NSObject @property (nonatomic, assign) NSInteger objectId; @property (nonatomic, copy) NSString *name; @property (nonatomic, strong) NSArray<RSRFDAModel *> *beans; @end #import "RSRFDAModel.h" @interface RSRFDAModel () <NSCopying> @end @implementation RSRFDAModel -(id)copyWithZone:(NSZone *)zone { RSRFDAModel *model = [[[self class] allocWithZone:zone] init]; model.objectId = self.objectId; model.name = self.name; model.beans = [self.beans mutableCopy]; return model; } @end 

如何实现深层复制:

 /// Class Foo has two properties: month and category - (id)copyWithZone:(NSZone *zone) { Foo *newFoo; if ([self.superclass instancesRespondToSelector:@selector(copyWithZone:)]) { newFoo = [super copyWithZone:zone]; } else { newFoo = [[self.class allocWithZone:zone] init]; } newFoo->_month = [_month copyWithZone:zone]; newFoo->_category = [_category copyWithZone:zone]; return newFoo; }