programing tip

copyWithZone 구현시 모범 사례 :

itbloger 2020. 10. 22. 07:45
반응형

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에서 :

  1. 클래스 이름을 직접 쓰는 것이 가장 좋습니까? [[Crime allocWithZone:zone] init]아니면 사용해야 [[[self Class] allocWithZone:zone] init]합니까?

  2. [self month]iVar를 복사하는 데 사용할 _month있습니까? 아니면 iVar에 직접 액세스해야 합니까?


  1. [[self class] allocWithZone:zone]적절한 클래스를 사용하여 복사본을 만들고 있는지 항상을 사용해야 합니다. 002에 대해 제공 한 예제는 그 이유를 정확히 보여줍니다. 서브 클래스는 [super copyWithZone:zone]수퍼 클래스의 인스턴스가 아닌 적절한 클래스의 인스턴스를 호출 하고 다시 가져올 것으로 예상합니다.

  2. ivar에 직접 액세스하므로 나중에 속성 설정자 (예 : 알림 생성)에 추가 할 수있는 부작용에 대해 걱정할 필요가 없습니다. 하위 클래스는 모든 메서드를 재정의 할 수 있습니다. 귀하의 예에서는 ivar 당 두 개의 추가 메시지를 보냅니다. 다음과 같이 구현합니다.

암호:

- (id)copyWithZone:(NSZone *)zone {
    Crime *newCrime = [super copyWithZone:zone];
    newCrime->_month = [_month copyWithZone:zone];
    newCrime->_category = [_category copyWithZone:zone];
    // etc...
    return newCrime;
}

물론 ivar를 복사하든, 보유하든, 아니면 그냥 할당하든 setter가하는 일을 반영해야합니다.


copyWithZone:SDK 제공 객체가있는 메소드 의 기본 복사 동작 은 "얕은 복사"입니다. 수단은 당신이 호출하면 그건 copyWithZone:NSString객체가 얕은 복사가 아니라 깊은 사본이 생성됩니다. 얕은 복사와 깊은 복사의 차이점은 다음과 같습니다.

개체의 얕은 복사본은 원본 배열의 개체에 대한 참조 만 복사하여 새 배열에 배치합니다.

전체 복사는 실제로 개체에 포함 된 개별 개체를 복사합니다. 이는 각 개별 객체 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

딥 카피를 구현하는 것은 어떻습니까?

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

참고 URL : https://stackoverflow.com/questions/9907154/best-practice-when-implementing-copywithzone

반응형