[objective-c] 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;
}


답변

Apple 문서에 따르면

copyWithZone : 메소드의 서브 클래스 버전은 서브 클래스가 NSObject에서 직접 내려 오지 않는 한 구현을 통합하기 위해 먼저 super에 메시지를 보내야합니다.

기존 답변에 추가

@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];

이 줄 obj은 (내가 가정) 선언 된 속성 을 통해 액세스하기 때문에 메모리 누수가 발생 한다고 생각 retain합니다. 따라서 보유 횟수 는 속성 및 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를 호출하므로 부작용이 발생할 수 있습니다.


답변