2010-06-06 2 views
2

NSCopying을 구현하려고하는 읽기 전용 속성을 가진 객체가 있습니다. "subConditions"("SubCondition"객체를 포함)라고하는 mutableArray가 있습니다. 호출자가 배열의 데이터를 변경할 수 있지만 배열 자체는 변경할 수 없도록하려는 경우 읽기 전용으로 만들었습니다. 이것은 -copyWithZone : 메소드를 작성할 때까지는 정말 잘 돌아갔다.읽기 전용을 복사하는 올바른 방법 NSMutableArray

조금 뒤죽박죽이 된 후에, 나는 그럭저럭 일하는 것처럼 보이는 것을 얻을 수 있었다. 그것은 최선의 관행인지 잘 모르겠습니다. 여기 내 -copyWithZone의 단순화 된 버전은 다음과 같습니다 방법 :

-(id)copyWithZone:(NSZone*)zone 
{ 
    Condition *copy = [[[self class]allocWithZone:zone]init]; 


NSArray *copiedArray = [[NSArray alloc]initWithArray:self.subConditions copyItems:YES]; 
[copy.subConditions setArray:copiedArray]; 
[copiedArray release]; 

    return copy; 
} 

이는 읽기 전용 mutableArray를 복사 할 올바른/가장 좋은 방법이 있나요?

답변

2

호출자가 배열의 데이터는 변경할 수 있지만 배열 자체는 변경할 수 없도록하려는 경우 [가변 배열 속성]을 읽기 전용으로 변경했습니다.

모질없이 객체 속성의 값을 변경하는 것은 나쁜 모조입니다. 예를 들어, 오브젝트가 어떤 오브젝트가 선택되었는지를 아는 인덱스 세트가 있다고 가정하십시오. 그런 다음 다른 객체가 배열에서 일부 하위 조건을 제거하면 세트의 일부 또는 모든 색인이 잘못된 객체 또는 객체를 참조 할 수 있습니다. 즉, 선택된 하위 조건에 액세스하면 NSOutOfRangeException이 발생합니다.

이것은 나쁜 습관입니다. 해결책은 역 습관으로 전환하는 것인데, 결코 이것을하지 않아야합니다. 소유주에게 변경 사항을 적용하도록하거나 적어도 변경 사항이 적용된 배열을 만들어 원래 배열 소유자에게 표시하여 소유 된 배열을 항상 변경하십시오. 소유자 (Condition)는 후자의 솔루션에서 인덱스 세트를 지우고 선택 항목을 잊어 버릴 수 있지만 예외를 발생시키는 것보다 여전히 좋습니다.

일단 NSMutableArray에서 NSArray로 속성 유형을 변경하면 NSMutableArrays 만 setArray:에 응답하므로 위 코드는 경고를 표시해야합니다. 코드는 여전히 으로 작동합니다. 접근자는 subConditions 접근 자로 자동 배열 된 복사본이 아닌 가변 배열을 반환하지만 컴파일러는 경고를 표시합니다. 테이블에서 배열을 변경하면 문제는 조건을 활성화하는 방법이됩니다. 클래스는 복사 된 하위 조건의 복사 된 배열로 Condition 인스턴스의 복사본을 제공하고 다른 클래스에서는 복사 할 수 없도록합니다.

한 가지 해결 방법은 단순히 새 배열을 복사본의 인스턴스 변수에 직접 저장하는 것입니다. 일반적으로 이것은 또한 나쁜 모조가 될 것이지만,이 특정 상황 (copyWithZone:, 영향을받는 오브젝트가 사본으로되어 있음)에서 이것은 적절한 경우가 거의 드문 경우 중 하나입니다. 그렇게 포인터 - 투 - 멤버 연산자를 사용합니다 :

copy->subConditions = [[NSMutableArray alloc]initWithArray:self.subConditions copyItems:YES]; 

다른 솔루션이 클래스의 구현 파일 내에서 readwrite로 속성을 다시 선언하는 class extension을 사용하는 것입니다. (클래스의 헤더 파일에 readonly 선언을하십시오.) 그런 다음 사용할 수있는 속성 액세스 메시지 : 속성을 : 직접 바르 액세스가 약간 빠른 것을 제외하고, 다른 이상을 추천 많이가 아니다

copy.subConditions = [[[NSArray alloc]initWithArray:self.subConditions copyItems:YES]autorelease]; 

버전은 임시 배열을 만들고 접근 자 메시지를 보내어 새 Condition이 해당 배열 복사본을 만들도록합니다. 속성 액세스 버전을 먼저 사용하고 Instrument를 사용하여 응용 프로그램의 프로필을 작성하여 관심있는 하드웨어의 오버 헤드가 중요한지 여부를 확인할 수 있습니다.

+0

매우 철저한 설명에 감사드립니다! –

+0

"NSMutableArrays 만 setArray에 응답하기 때문에 :"NSMutableArrays는 그런 것에 응답하지 않습니다. – user102008

+1

@ user102008 : 가능합니다. http://developer.apple.com/mac/library/documentation/Cocoa/Reference/Foundation/Classes/NSMutableArray_Class/Reference/Reference.html%23//apple_ref/occ/instm/NSMutableArray/setArray%3A –

관련 문제