2010-08-03 2 views
1

현재 수도 쿠 응용 프로그램에서 작업 중입니다. 숫자는 NSNumbers의 다차원 NSMutableArray 내에 저장됩니다. 그리드에 숫자를 표시하기 위해 SudokuGridView에 배열을 유지합니다. 퍼즐을 풀 때가되면, 퍼즐을 풀기 위해 만든 NSOperation의 서브 클래스에 [grid numberGrid]를 전달합니다.다차원 NSMutableArray 복사

그리드의 배열이 같은 속성으로 정의된다

@property (readonly) NSMutableArray *numberArray; 

스도쿠 그리드 솔버에 전달 내가 가서 :

MESudokuSolver *solvePuzzleOperation = [[MESudokuSolver alloc] initWithPuzzle: [grid numberArray]]; 

initWithPuzzle 그래서 다음과 같이 정의된다

- (id)initWithPuzzle:(NSMutableArray *)puzzleArray { 
    if(self = [super init]) { 
     puzzle = [[NSMutableArray alloc] initWithArray: puzzleArray]; 
    } 
    return self;  
} 

그런 다음 퍼즐을 프리미티브 int 배열로 변환하여 해결 한 다음 퍼즐로 돌아갑니다. NSMutab leArray. 웃기는 것은 재미 있습니다. 이제는 그리드의 NSMutableArray에 솔루션이 있습니다. 즉, 어떻게 든 MESudokuSolver 내부에서 그리드의 배열이 수정되고 있음을 의미합니다. 그래서 몇 가지 조사를했는데 MESudokuSolver 인스턴스로 전달 된 배열에 대한 포인터는 MESudokuSolver의 NSMutableArray 퍼즐과 다릅니다. 이상하지? 알아.

추가 조사를 통해 다른 포인터가있는 배열 내부의 NSNumber에 대한 포인터는 실제로 동일합니다.

당신에게 StackOverflow, 나는 WTF를 묻는가?

답변

1

다른 배열의 내용으로 배열을 초기화하면 두 배열의 내용이 동일한 객체를 참조합니다. 당신이하고 싶은 것은 깊은 사본을 수행하는 것입니다. 이렇게하면 각 배열이 객체의 자체 사본을 참조하므로 하나의 배열에서 객체를 수정하면 실제로 다른 객체이기 때문에 다른 배열의 객체에는 영향을 미치지 않습니다. 이것은 배열의 배열에도 적용됩니다. 깊은 사본을 수행하는 데는 여러 가지 방법이 있습니다. 당신이 당신의 변경 가능한 배열 내부에 가변 배열의 변경 가능한 사본을 원하기 때문에, 그것은 쉽게 그럼에도 불구하고 조금 까다 롭습니다하지만 :

// Implemented as a free function here, but this is not required. 

NSMutableArray *MECopyGrid(NSMutableArray *outer) 
{ 
    NSMutableArray *result = [[NSMutableArray alloc] initWithCapacity:[outer count]]; 

    for (NSMutableArray *inner in outer) 
    { 
     NSMutableArray *theCopy = [inner mutableCopy]; 
     [result addObject:theCopy]; 
     [theCopy release]; 
    } 

    return result; 
} 

가의 NSNumber의 최적화의 또한 조심하십시오. 코코아 (그리고 나는 또한 코코아 터치 가정) 몇 가지 NSNumber 인스턴스를 캐시합니다. NSNumber 인스턴스가 변경 불가능하기 때문에 [NSNumber numberWithInteger:1]을 요청하면 Cocoa가 동일한 값을 포함하는 기존 인스턴스에 대한 참조를 제공 할 수 있습니다. NSNumber 인스턴스 포인터가 동일하다는 것을 알게되면 코코아가 이전 인스턴스를 제공했기 때문일 수 있습니다. 이것은 당신 같은 상황에서 특히 메모리를 절약 할 수 있습니다. (최적화가 없다면 NSNumber의 81 개의 독립 인스턴스가 필요하지만 최적화는 9 개만 필요합니다).

+0

감사합니다. 전에 실제로 다차원 NSArrays로 작업 한 적이 없기 때문에 이전에는이 ​​문제가 실제로 발생하지 않았습니다. 여기에 명확한 질문을 할 수 있다면 ... 왜 1 차원 배열이 ... NSStrings라고하면 그 문자열이 실제로 메모리에 복사되고 다른 인스턴스에서 직접 수정되지 않는다는 것입니까? –

+0

@Matt Egan : 당신이 무슨 뜻인지 정확히 모르겠습니다. 당신이 불변의 문자열 배열을 가지고 있다면, 아마도 메모리에 복사되지 않을 것입니다. 불변의 문자열을 수정할 수있는 것은 없으므로'copy'는 간단한'retain'이됩니다. 불변의 캐릭터 라인을 포함한 배열의 카피를 작성하면, 양쪽 모두의 배열에, 같은 불변 인 캐릭터 라인에의 참조가 포함됩니다. 개체를 수정할 때 걱정할 필요가있는 유일한 경우는 배열에 * 변경 가능한 * 개체가있는 경우입니다. 객체가 변경 가능하게 유지되기를 원하지만 다른 객체를 변경하지 않으려면'mutableCopy'를 얻어야합니다. – dreamlax

+0

그것은 총체적인 감각을 다시 만든다! –