簡體   English   中英

如何在Objective-C中復制對象

[英]How to copy an object in Objective-C

我需要深度復制一個具有自己對象的自定義對象。 我一直在閱讀,對於如何繼承 NSCopying 以及如何使用 NSCopyObject 感到有些困惑。

與引用類型一樣,“復制”有兩個概念。 我相信你知道他們,但為了完整性。

  1. 按位復制。 在這里,我們只是逐位復制內存 - 這就是 NSCopyObject 所做的。 幾乎總是,這不是您想要的。 對象具有內部狀態、其他對象等,並且經常假設它們是唯一持有對該數據的引用的對象。 按位復制打破了這個假設。
  2. 一個深刻的、合乎邏輯的副本。 在這里,我們制作了對象的副本,但實際上並沒有一點一點地做——我們想要一個對象在所有意圖和目的上的行為都相同,但不是(必然)原始內存相同的克隆—— Objective C 手冊稱這樣的對象與其原始對象“功能獨立”。 因為制作這些“智能”副本的機制因類而異,所以我們要求對象本身執行它們。 這是 NSCopying 協議。

你想要后者。 如果這是您自己的對象之一,您只需采用 NSCopying 協議並實現 -(id)copyWithZone:(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;
}

蘋果文檔說

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;
}

我不知道那個代碼和我的有什么區別,但是我對那個解決方案有問題,所以我讀了一點,發現我們必須在返回之前設置對象。 我的意思是這樣的:

#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;
}

我添加了這個答案是因為我在這個問題上有很多問題,我不知道為什么會這樣。 我不知道有什么區別,但它對我有用,也許對其他人也有用:)

another.obj = [obj copyWithZone: zone];

我認為,這一行會導致內存泄漏,因為您可以通過(我假設)聲明為retain屬性訪問obj 因此,保留計數將通過 property 和copyWithZone增加。

我認為應該是:

another.obj = [[obj copyWithZone: zone] autorelease];

要么:

SomeOtherObject *temp = [obj copyWithZone: zone];
another.obj = temp;
[temp release]; 

還可以使用 -> 運算符進行復制。 例如:

-(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.

非常簡單直接。 :P

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM