Iphone 实施copyWithZone时的最佳实践:
我正试图弄清楚关于实现Iphone 实施copyWithZone时的最佳实践:,iphone,objective-c,cocoa-touch,copywithzone,Iphone,Objective C,Cocoa Touch,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]];
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,即\u month
[[self class]allocWithZone:zone]
来确保使用适当的类创建副本。您为002给出的示例确切地说明了为什么:子类将调用[super copyWithZone:zone]
,并期望返回相应类的实例,而不是超级类的实例当然,无论您是复制IVAR、保留IVAR,还是仅仅分配IVAR,都应该反映setter的工作。SDK提供的对象的
copyWithZone:
方法的默认复制行为是“浅复制”。这意味着,如果在NSString
对象上调用copyWithZone:
,它将创建浅拷贝,但不会创建深拷贝。浅拷贝和深拷贝的区别是:
对象的浅层副本将仅复制对原始数组对象的引用,并将其放置到新数组中
深度复制实际上会复制对象中包含的各个对象。这是通过在自定义类方法中向每个对象发送copyWithZone:
消息来完成的
INSHORT:要获得浅拷贝,您可以对所有实例变量调用retain
或strong
。要获得深度复制,请对自定义类copyWithZone:
实现中的所有实例变量调用copyWithZone:
。现在由您选择。这是我的型号
#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
#导入
@接口RSRFDAModel:NSObject
@属性(非原子,赋值)NSInteger objectId;
@属性(非原子,副本)NSString*名称;
@属性(非原子,强)NSArray*豆;
@结束
#导入“RSRFDAModel.h”
@接口RSRFDAModel()
@结束
@RSRFDAModel的实现
-(id)copyWithZone:(NSZone*)区{
RSRFDAModel*model=[[[self class]allocWithZone:zone]init];
model.objectId=self.objectId;
model.name=self.name;
model.beans=[self.beans mutableCopy];
收益模型;
}
@结束
这个实现深度复制的怎么样:
/// 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;
}
选择这两种方法中的哪一种取决于超类是否实现了
NSCopying
。例如,NSObject
没有,因此调用[super-copyWithZone:zone]
将抛出一个异常。它说/Users/ws403216/Desktop/Demo/Demo/Crime.m:21:28:No-visible@interface For'NSObject'声明了选择器“copyWithZone:”super-class of-Crime.m在我的例子中是NSObject.@NitinMalguri,正如前面的评论所指出的,如果父类支持NSCopying,则只应调用[super copyWithZone:zone]
,否则应调用[[self class]allocWithZone:zone]init]
并根据需要复制字段。默认复制行为应为浅复制,但您提供了深复制的解决方案。浅复制和深复制的区别在于:对象的浅复制只会复制对原始数组对象的引用,并将它们放置到新数组中。深度复制实际上会复制对象中包含的各个对象。通过向每个对象发送“copyWithZone:”消息,可以澄清误解
/// 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;
}