我目前正在开发数独应用程序,数字存储在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?
答案 0 :(得分: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个优化)。