Objective c 复制多维NSMutableArray

Objective c 复制多维NSMutableArray,objective-c,cocoa-touch,nsmutablearray,nsarray,nscopying,Objective C,Cocoa Touch,Nsmutablearray,Nsarray,Nscopying,我目前正在开发一个数独应用程序,这些数字存储在一个多维NSMUTABLE NSNumbers数组中。我在SudokuGridView中保留了一个数组,用于显示网格中的数字。当需要解决难题时,我将[grid numberGrid]传递给我创建的用于解决难题的NSOperation的子类 网格的数组定义为以下属性: @property (readonly) NSMutableArray *numberArray; 将其传递到数独网格解算器时,我会: MESudokuSolver *solvePu

我目前正在开发一个数独应用程序,这些数字存储在一个多维NSMUTABLE NSNumbers数组中。我在SudokuGridView中保留了一个数组,用于显示网格中的数字。当需要解决难题时,我将[grid numberGrid]传递给我创建的用于解决难题的NSOperation的子类

网格的数组定义为以下属性:

@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数组来解决它,然后返回到谜题NSMutableArray。有趣的是,网格的NSMutableArray现在有了解决方案。。。这意味着在MESudokuSolver内部,网格的数组正在被修改。所以我做了一些调查,指向传入MESudokuSolver实例的数组的指针不同于MESudokuSolver的拼图NSMutableArray。奇怪吧?我知道

经过进一步研究,在具有不同指针的数组中,指向NSNumbers的指针实际上是相同的


我问你,当你用另一个数组的内容初始化一个数组时,两个数组的内容将引用相同的对象。您要做的是执行深度复制。这样可以确保每个数组引用其自身的对象副本,因此如果修改一个数组中的对象,则不会影响另一个数组中的对象,因为它们实际上是不同的对象。这甚至适用于数组的数组。执行深度复制有多种方法。由于您希望在可变数组中包含可变数组的可变副本,因此这有点棘手,但很容易:

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

还要注意数量优化。Cocoa(我假设Cocoa Touch也会)缓存几个不同的NSNumber实例。由于NSNumber实例是不可变的,如果您请求
[NSNumber numberWithInteger:1]
,Cocoa可能会提供对包含相同值的现有实例的引用。如果您注意到NSNumber实例指针是相同的,可能是因为Cocoa给了您一个旧实例。这将节省内存,特别是在像您这样的情况下(如果没有优化,您将需要81个独立的NSNumber实例,但进行优化,您最多只需要9个)。

当您使用另一个数组的内容初始化一个数组时,两个数组的内容将引用相同的对象。您要做的是执行深度复制。这样可以确保每个数组引用其自身的对象副本,因此如果修改一个数组中的对象,则不会影响另一个数组中的对象,因为它们实际上是不同的对象。这甚至适用于数组的数组。执行深度复制有多种方法。由于您希望在可变数组中包含可变数组的可变副本,因此这有点棘手,但很容易:

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

还要注意数量优化。Cocoa(我假设Cocoa Touch也会)缓存几个不同的NSNumber实例。由于NSNumber实例是不可变的,如果您请求
[NSNumber numberWithInteger:1]
,Cocoa可能会提供对包含相同值的现有实例的引用。如果您注意到NSNumber实例指针是相同的,可能是因为Cocoa给了您一个旧实例。这将节省内存,特别是在像您这样的情况下(如果没有优化,您将需要81个独立的NSNumber实例,但进行优化,您最多只需要9个)。

谢谢!我以前从未真正遇到过这个问题,可能是因为我以前从未使用过多维NSArray。如果我能问一个简单的问题来澄清。。。为什么如果你有一个一维数组,比如说。。。NSStrings,这些字符串实际上是在内存中复制的,而不是直接从另一个实例修改的?@Matt Egan:我不太清楚你的意思。如果您有一个不可变字符串数组,它们可能永远不会被复制到内存中。因为没有任何东西可以修改不可变字符串,所以
副本
变成了一个简单的
保留
。如果创建包含不可变字符串的数组的副本,则两个数组都将包含对相同不可变字符串的引用。只有当数组包含可变对象时,才需要修改对象。如果你想让一个对象保持可变,但不想让其他任何东西改变它,你必须得到一个
mutableCopy
。谢谢!我以前从未真正遇到过这个问题,可能是因为我以前从未使用过多维NSArray。如果我能问一个简单的问题来澄清。。。为什么如果你有一个一维数组,比如说。。。NSStrings,这些字符串实际上是在内存中复制的,而不是直接从另一个实例修改的?@Matt Egan:我不太清楚你的意思。如果您有一个不可变字符串数组,它们可能永远不会被复制到内存中。因为没有任何东西可以修改不可变字符串,所以
副本
变成了一个简单的
保留
。如果创建包含不可变字符串的数组的副本,则两个数组都将包含对相同不可变字符串的引用。只有当数组包含可变对象时,才需要修改对象。如果您希望一个对象保持可变,但不希望其他任何东西对其进行更改,则必须获得
mutableCopy