实施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:
-
最好直接编写类名
[[Crime allocWithZone:zone] init]
还是应该使用[[[self Class] allocWithZone:zone] init]
? -
可以使用
[self month]
来复制iVar,还是直接访问iVar,即_month
?
-
你应该总是使用
[[self class] allocWithZone:zone]
来确定你正在使用适当的类创build一个副本。 你给002的例子显示了原因:子类将调用[super copyWithZone:zone]
并期望获得适当类的实例,而不是超类的实例。 -
我直接访问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调用retain
或strong
。 要获得深层副本,请调用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; }