我需要深度复制一个自定义对象,它有自己的对象。我一直在阅读,对于如何继承 NSCopying 和如何使用 NSCopyObject 感到有点困惑。
与引用类型一样,“复制”有两个概念。我相信你们都知道,但是为了完整起见。
你想要后者。如果这是您自己的对象之一,您只需采用协议 NSCopying 并实现-(id) copWithZone: (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; }
苹果的文件显示
CopWithZone: 方法的子类版本应该发送消息 超级优先,合并它的实现,除非子类 直接从 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; }
another.obj = [obj copyWithZone: zone];
我认为,这一行会导致内存泄漏,因为您通过(我假设)声明为 retain的属性访问 obj。因此,保留计数将增加的性质和 copyWithZone。
retain
obj
copyWithZone
我认为应该是:
another.obj = [[obj copyWithZone: zone] autorelease];
or:
SomeOtherObject *temp = [obj copyWithZone: zone]; another.obj = temp; [temp release];
我不知道那段代码和我的有什么不同,但是我在这个解决方案上遇到了一些问题,所以我又读了一些,发现我们必须在返回对象之前设置它。我的意思是:
#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; }
我加上这个答案是因为我在这个问题上有很多问题,而且我不知道为什么会发生这种情况。我不知道其中的区别,但它对我很有用,也许对其他人也有用:)
还可以使用-> 操作符进行复制。例如:
-(id)copyWithZone:(NSZone*)zone { MYClass* copy = [MYClass new]; copy->_property1 = self->_property1; ... copy->_propertyN = self->_propertyN; return copy; }
这里的推理是,由此产生的复制对象应该反映原始对象的状态。那个运算符可能会引入副作用,因为这个运算符调用 getter 函数,而 getter 函数又可能包含逻辑。
这种方式可能不受欢迎,但我是这么做的:
object1 = // object to copy YourClass *object2 = [[YourClass alloc] init]; object2.property1 = object1.property1; object2.property2 = object1.property2; .. etc.
Quite simple and straight forward. :P