我试图理解将对象从一个NSMutableArray复制到另一个NSMutableArray。考虑以下两种情况: 1 - 将原件复制到克隆,克隆中的更改将影响原件。 2 - 将原件复制到克隆,其中关闭的更改不会影响原件。
首先,我尝试使用以下代码首先生成场景#1。根据我的理解,当复制数组不使用'mutablecopy'时,克隆数组将只保存指向原始字符串对象的指针。因此,如果我要将克隆的第一个元素更改为另一个对象,原始的第一个元素会改变得太对吗? ......但这不是我得到的结果。为什么呢?
事实上,当我使用mutablecopy时
[self.cloneArray addObject:[[self.originalArray objectAtIndex:i] mutableCopy]];
我得到了相同的结果。我很困惑。
ArrayClass.h
@interface ArrayClass : NSObject {
NSMutableArray *_originalArray;
NSMutableArray *_cloneArray;
}
@property (nonatomic, retain) NSMutableArray *originalArray;
@property (nonatomic, retain) NSMutableArray *cloneArray;
ArrayClass.m
@synthesize originalArray = _originalArray;
@synthesize cloneArray = _cloneArray;
_originalArray = [[NSMutableArray alloc] initWithObjects: @"one", @"two", @"three", @"four", @"five", nil];
_cloneArray = [[NSMutableArray alloc] initWithCapacity:[self.originalArray count]];
for (int i=0; i<5; i++) {
[self.cloneArray addObject:[self.originalArray objectAtIndex:i]];
}
// make change to the first element of the clone array
[self.cloneArray replaceObjectAtIndex:0 withObject:@"blah"];
for (int n=0; n<5; n++) {
NSLog(@"Original:%@ --- Clone:%@", [self.originalArray objectAtIndex:n], [self.cloneArray objectAtIndex:n]);
}
...
2011-03-27 03:23:16.637 StringTest[1751:207] Original:one --- Clone:blah
2011-03-27 03:23:16.638 StringTest[1751:207] Original:two --- Clone:two
2011-03-27 03:23:16.639 StringTest[1751:207] Original:three --- Clone:three
2011-03-27 03:23:16.642 StringTest[1751:207] Original:four --- Clone:four
2011-03-27 03:23:16.643 StringTest[1751:207] Original:five --- Clone:five
答案 0 :(得分:8)
你正在考虑这种方式。
在Objective-C中,您有对象的引用。 NSString *foo;
只是定义了引用foo
的变量NSString
。如果您说NSString *bar = foo;
,那么bar
将引用foo
引用的任何对象。不多也不少。
NSArray
只是对象引用的集合。所以,如果你说:
NSArray *b = [NSArray arrayWithArray: a];
您正在创建一个数组b
,其中包含与a
完全相同的对象集的所有相同引用。如果您修改a
引用的对象,那将是b
中完全相同的对象,并且将反映修改。
当您复制对象时,您正在创建一个与原始内容状态相同的 new 对象。即当您说NSMutableString *foo = [barString mutableCopy];
时,foo
是对 new 字符串的引用;与barString
不同的一个。
所以...在创建一个新数组时,问题是您希望数组包含与原始数组完全相同的内容,还是希望它包含 new 对象集?你可以修改吗?
答案 1 :(得分:5)
你对正在发生的事情有误解。 replaceObjectAtIndex:withObject:
调用不是修改数组中的对象,而是修改数组本身。在这一行之后:
[self.cloneArray replaceObjectAtIndex:0 withObject:@"blah"];
您已经替换了克隆数组中的对象,但您根本没有更改原始数组。如果您实际修改了 在数组中的NSString
对象,则可能会获得您期望的行为。但不能能够使用您在示例中放入原始数组的对象,因为它们是不可变的字符串对象。如果你在那里插入了可变字符串,使用相同的循环来“克隆”你的数组,然后按照以下方式做一些事情:
[[self.cloneArray objectAtIndex:0] appendString:@"some junk to append"];
你实际上会修改索引0处的字符串对象。由于两个数组仍然包含同一个对象,因此你可以通过改变克隆数组中的对象来获得“修改原始数组”的行为。