我应该使用副本还是强数组?

时间:2014-11-18 11:38:38

标签: ios objective-c automatic-ref-counting

我在谈论ARC项目。

我总是声明像这样的数组属性

@property (strong, nonatomic) NSArray *myArray;

但我看到很多人建议使用它:

@property (copy, nonatomic) NSArray *myArray;

人们建议复制说" myArray上的副本是为了防止另一个"所有者"您设置的对象。"这个"解释"克林顿对我说话。

有人可以在我5岁时解释这个含义吗?好的,把它变成3。

感谢

4 个答案:

答案 0 :(得分:13)

复制很浅,它只复制指针。如果数组包含可变对象并且该对象已更改,则更改将显示在复制的数组中。

NSMutableString *s = [@"test1" mutableCopy];
NSArray *a1 = @[s];
NSArray *a2 = [a1 copy];
NSLog(@"\na1: %1$p, %1$@\na2: %2$p, %2$@", a1, a2);
[s appendString:@"2"];
NSLog(@"\na1: %1$p, %1$@\na2: %2$p, %2$@", a1, a2);     

输出:

a1: 0x10010fed0, (
    test1
)
a2: 0x10010fed0, (
    test1
)

a1: 0x10010fed0, (
    test12
)
a2: 0x10010fed0, (
    test12
)

复制的原因是为了在被复制的数组是可变数组的情况下进行保护,以便原始数组的任何更改都不会更改复制的数组。不同之处在于可变数组的变化和可变数组中对象的变化。注意,进一步的原因是人们可能不知道被分配的数组是否可变。

NSString *s1 = @"test1";
NSString *s2 = @"test2";
NSMutableArray *a1 = [@[s1] mutableCopy];
NSArray *a2 = [a1 copy];
NSLog(@"\na1: %1$p, %1$@\na2: %2$p, %2$@", a1, a2);
[a1 addObject:s2];
NSLog(@"\na1: %1$p, %1$@\na2: %2$p, %2$@", a1, a2);

输出:

a1: 0x100200510, (
    test1
)
a2: 0x100200650, (
    test1
)

a1: 0x100200510, (
    test1,
    test2
)
a2: 0x100200650, (
    test1
)

请注意,不可变NSArray上的副本只执行赋值,因此不需要任何成本。当分配的数组是NSMutableArray时,只有一个副本。

NSString *s1 = @"test1";
NSString *s2 = @"test2";
NSArray *a1 = @[s1];
NSArray *a2 = [a1 copy];
NSLog(@"\na1: %1$p, %1$@\na2: %2$p, %2$@", a1, a2);

输出:

a1: 0x100300140, (
    test1
)
a2: 0x100300140, (
    test1
)

答案 1 :(得分:2)

问题是,在设置属性后,数组可能会发生变异,即使该属性被定义为不可变数组。例如,考虑一下,

NSMutableArray *array = [NSMutableArray arrayWithObjects:@1, @2, @3, nil];
obj.myArray = array;
[array addObject:@4];

如果将myArray定义为strong,则通过更改本地可变数组也会更改myArray的{​​{1}}属性。

通过将obj定义为myArray,可确保您不必担心数组本身会发生变异。

您仍然需要担心数组中的对象发生变化,如果这也是一个问题,您可能会考虑进行深层复制。

答案 2 :(得分:1)

很简单,请在视图控制器的某处考虑

NSArray *myArrayCopy = self.myArray

现在如果myArray很强,那么如果你更改myArrayCopy中的某个对象,myArray会自动更改。而在复制的情况下,它不会改变,因为它会将myArray的副本分配给myArrayCopy。

答案 3 :(得分:1)

这取决于您是否要处理相同的数据。 copy确实也是“强”的,因此在强指针设置为nil之前,对象不会被销毁。 但是,强大的引用同一个对象,而副本引用对象的副本。生成的setter类似于:

-(void)setStrongArray:(NSArray*)data
{
   _strongArray = data;
}

-(void)setCopyArray:(NSArray*)data
{
   _strongArray = [data copy];
}