【问题标题】:Copying Multi-Dimensional NSMutableArray复制多维 NSMutableArray
【发布时间】:2010-08-03 02:48:40
【问题描述】:

我目前正在开发一个数独应用程序,数字存储在 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?

【问题讨论】:

    标签: objective-c cocoa-touch nsmutablearray nsarray nscopying


    【解决方案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 个)。

    【讨论】:

    • 谢谢!我以前从未真正遇到过这个问题,可能是因为我以前从未使用过多维 NSArrays。如果我可以在这里问一个简单的问题来澄清...为什么如果您有一个一维数组说... NSStrings,这些字符串实际上是在内存中复制而不是直接从另一个实例修改的?
    • @Matt Egan:我不太清楚你的意思。如果您有一个不可变字符串数组,它们可能永远不会被复制到内存中。由于没有任何东西可以修改不可变的字符串,copy 变成了简单的retain。如果您创建包含不可变字符串的数组的副本,则两个数组都将包含对相同不可变字符串的引用。唯一需要修改对象的时候是当你的数组包含 mutable 对象时。如果你想让一个对象保持可变但你不想改变它,你必须得到一个mutableCopy
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-08-11
    • 1970-01-01
    相关资源
    最近更新 更多