newArray = array 和 newArray = [array copy] 有什么区别



我有这样几行代码:

- (void)redrawGraphWithArray:(NSArray *)array {
    _graphView.graphPoints = [array copy];
    [_graphView setNeedsDisplay];
}

graphPoints也是NSArray。

如果我使用

_graphView.graphPoints = array;

图表看起来是一样的,没有问题。

我想知道两者之间的区别

_graphView.graphPoints = [array copy]

_graphView.graphPoints = array;

谢谢。

_graphView.graphPoints = array;将graphPoints指定为与原始对象相同的数组。您只是在创建另一个指向完全相同内存的指针。例如,这将发生:

NSMutableArray *array = [[NSMutableArray alloc] init];
array[0] = @{@"x": @1, @"y": @2};
array[1] = @{@"x": @1, @"y": @3};
_graphView.graphPoints = array;
// Now let's make some changes to the original array
// Note that I used an NSMutableArray to explain fully the differences between
// the two assignment types.
array[0] = @{@"x": @1, @"y": @1}; // With an NSArray you wouldn't be able to do this
array[1][@"y"] = @5;              // But this can still happen
// What happens to graphPoints?
_graphView.graphPoints[0]; // <== {x: 1, y: 1}
_graphView.graphPoints[1]; // <== {x: 1, y: 5}

在这种情况下,graphPoints指向与array完全相同的对象,因此两者保持完全相同。代码示例中没有说明,但请务必记住,这种"相同性"指向两个方向,因此对graphPoints进行更改也会更改array

另一方面,[array copy]创建一个新的数组对象,该对象是原始数组对象的副本,因此上面的代码将产生不同的结果:

NSMutableArray *array = [[NSMutableArray alloc] init];
array[0] = @{@"x": @1, @"y": @2};
array[1] = @{@"x": @1, @"y": @3};
_graphView.graphPoints = [array copy];
// Now let's make the same changes to the original array
array[0] = @{@"x": @1, @"y": @1};
array[1][@"y"] = @5;
// What happens to graphPoints?
_graphView.graphPoints[0]; // <== {x: 1, y: 2}
_graphView.graphPoints[1]; // <== {x: 1, y: 5}

第一个对象在graphPoints中没有改变,因为我们在array中写入了一个全新的对象。由于graphPoints现在是副本,因此它没有受到影响。

但是,第二个对象确实发生了变化,因为我们没有将新对象写入array,而是修改了两个数组都包含的现有对象。这说明了对象复制的一个重要微妙之处。这就是所谓的"浅"副本,这意味着容器被复制,但其内容不会。你最终得到两个数组,但只有一组包含的对象。

有一些相对简单的方法也可以复制所有包含的对象,方法是确保包含的对象都实现NSCopying协议(如果您只是使用 NSDictionaryNSArrayNSNumberNSStringFoundation类,您不必担心,因为这已经为您完成(并在 NSArray 上使用 - initWithArray:copyItems: 初始值设定项。但是,即使这样也会创建所包含对象的浅拷贝,但是如果需要,有很多关于如何实现完整"深"拷贝的信息。

[array copy]将创建数组(具有相同内容(的新实例并将其分配给图形点。就像你只分配数组一样,graphpoints将具有与对象数组相同的引用。也就是说,两者都将指向同一对象。因此,如果您更改数组对象,那么它也将更改图形点。但是,如果您使用复制,情况并非如此。

这是一个过早的优化。

主要区别:第一种方法会产生一个自动发布的"副本",您不拥有该副本,也不必释放该副本,而您确实拥有在第二行创建的对象。顺便说一下,这两个数组都是不可变的。

最新更新