1

我目前正在开发一个数独应用程序,这些数字存储在 NSNumbers 的多维 NSMutableArray 中。我在 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 的指针实际上是相同的。

对你 StackOverflow,我问,WTF?

4

1 回答 1

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 优化。Cocoa(我也假设 Cocoa Touch)缓存了几个不同的 NSNumber 实例。由于 NSNumber 实例是不可变的,如果您要求[NSNumber numberWithInteger:1],Cocoa 可能会为您提供对包含相同值的现有实例的引用。如果你注意到 NSNumber 实例指针是相同的,很可能是因为 Cocoa 给了你一个旧实例。这将节省内存,尤其是在像您这样的情况下(如果没有优化,您将需要 81 个独立的 NSNumber 实例,但通过优化,您最多只需要 9 个)。

于 2010-08-03T03:24:11.827 回答