复制和引用NSObjects iOS

时间:2015-08-01 03:46:19

标签: ios objective-c arrays swift

所以有一段时间我一直在研究这个应用程序 - 其中包含一个类似文件夹的对象结构,它具有可以包含相同类型对象的数组属性,而这些对象又可以包含更多此对象,等等这些对象称为组。在共享数据类中,我有一个名为mainGroup的mater组对象,以及一个名为selectedGroup的数据类属性,以方便显示数据。这些组对象可以被修改,因此在相当长的一段时间内我尝试开发一个解决方案,使所有数组的路径到达所需的对象,同时不知道复制和指定一个数组等于其他不会创建深层副本,只是某种引用。代码在逻辑上是合理的,但是在一段时间之后,我注意到删除selectedGroup的数组属性中的内容对实际的主副本产生了相同的效果,这对我的应用程序做了一些不可思议的事情。

我做了一些谷歌搜索,并发现我实际上并没有创建一个全新的数组,只是引用它如何。我仍然对下一部分感到困惑。我认为将一个数组设置为等于另一个数组与调用其上的副本具有相同的效果 - 当我替换或删除一个数组中的对象时,另一个数组会受到影响。那么当你设置两个彼此相等的数组时,编译器究竟在做什么呢?它不应该仅使用指向旧数组中对象的指针来填充新数组,而不仅仅是引用数组本身吗?为什么在使用NSStrings这样的对象执行相同的操作时,您看不到相同的效果?最后,其他对象具有与NSArrays相同的行为?

2 个答案:

答案 0 :(得分:2)

  

那么当你设置两个彼此相等的数组时,编译器到底在做什么呢?

Objective-C中的许多不可变类实现-copy,以便该方法只保留原始对象并返回指向它的指针。例如,如果复制NSString的实例,则会返回指向同一对象的指针。因为对象是不可变的,所以无论你是否实际复制它都无关紧要 - 对象不能改变,副本完全相同,所以另一个指向原始对象的指针完全相同复制的方式。再次保留对象可确保至少在调用者完成对象之前不会销毁对象。

其他类也是如此,例如NSArray,可能NSDataNSDateNSNumber以及其他类。由于行为应该对客户透明,因此不需要全面的列表。

如果你真的使用NSArray的实例,很难理解你描述的问题会如何出现。您无法在NSArray中添加或删除对象 - 这就是该类不可变的含义。听起来你实际上正在处理一个可变数组(NSMutableArray),并且当你调用NSMutableString时,该类(以及其他类似-copy等)会生成实际的副本。

听起来你实际上并没有制作你正在使用的数组的副本,而只是将指针复制到了数组。例如:

NSArray *array1 = [NSMutableArray arrayWithObjects:@"foo", @"bar", nil];
NSArray *array2 = array1;

现在,上面的代码制作第一个数组的副本。你得到的是一个单独的数组,有两个指向它的变量。如果您对array1进行了更改,则会在array2中看到此更改,因为array1array2实际上只是同一个数组的两个名称。如果你想要一份副本,你可以这样做:

NSArray *array3 = [array1 copy];

现在,让我们做一个改变:

NSLog(@"Size of array1: %ld", [array1 count]);  // 2
NSLog(@"Size of array2: %ld", [array2 count]);  // 2
NSLog(@"Size of array3: %ld", [array3 count]);  // 2

[array1 removeObjectAtIndex:1];

NSLog(@"Size of array1: %ld", [array1 count]);  // 1
NSLog(@"Size of array2: %ld", [array2 count]);  // 1
NSLog(@"Size of array3: %ld", [array3 count]);  // 2

答案 1 :(得分:1)

问题在于,这就是对象的工作原理。无论何时使用对象,它都会传递对前一个对象的引用,而不是复制它并创建一个新对象,而NSArray本身就是对象。如果您想在问题中执行您所说的内容,则需要创建一个新数组并遍历数组中的每个单独对象并将其复制到新数组中。如果你正在使用objective-c,那么你没有其他任何具有此功能的东西,尽管你可以环顾NSArray以获得你想要的功能。如果你使用的是swift,你可以简单地创建数组(看here)。