在下面的程序当中 我们 将 可修改字符串 添加到 数组物件当中 以便于 我们 可以修改 数组物件中的某个字符串。研究一下 下面的程序,看看 你 能不能理解 程序运行的结果:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 | #import <Foundation/NSobject.h> #import <Foundation/NSArray.h> #import <Foundation/NSString.h> #import <Foundation/NSAutoreleasePool.h> int main(int argc,const char *argv[]) { NSAutoreleasePool *pool=[[NSAutoreleasePool alloc] init]; NSMutableArray *dataArray=[NSMutableArray arrayWithObjects: [NSMutableString stringWithString:@"One"], [NSMutableString stringWithString:@"Two"], [NSMutableString stringWithString:@"Three"], nil]; NSMutableArray *dataArray2; NSMutableString *mutableString; NSLog(@"dataArray:"); for(NSString *element in dataArray) { NSLog(@" %@",element); } //先复制数组物件dataArray,再改变其中一个字符串 dataArray2=[dataArray mutableCopy]; mutableString=[dataArray objectAtIndex:0]; [mutableString appendString:@"ONE"]; NSLog(@"dataArray:"); for(NSString *element in dataArray) { NSLog(@" %@",element); } NSLog(@"dataArray2:"); for(NSString *element in dataArray2) { NSLog(@" %@",element); } [dataArray2 release]; [pool drain]; return 0; } |
这个程序 运行过后,可以得到 这样的结果:
1
2
3
4
5
6
7
8
9
10
11
12
|
2012-06-04 15:57:30.091 Sample[1331:707] dataArray:
2012-06-04 15:57:30.093 Sample[1331:707] One
2012-06-04 15:57:30.094 Sample[1331:707] Two
2012-06-04 15:57:30.094 Sample[1331:707] Three
2012-06-04 15:57:30.095 Sample[1331:707] dataArray:
2012-06-04 15:57:30.096 Sample[1331:707] OneONE
2012-06-04 15:57:30.096 Sample[1331:707] Two
2012-06-04 15:57:30.097 Sample[1331:707] Three
2012-06-04 15:57:30.097 Sample[1331:707] dataArray2:
2012-06-04 15:57:30.098 Sample[1331:707] OneONE
2012-06-04 15:57:30.099 Sample[1331:707] Two
2012-06-04 15:57:30.099 Sample[1331:707] Three
|
我们 通过这行语句 将 数组物件dataArray中第0个物件 读取了出来:
| mutableString=[dataArray objectAtIndex:0]; |
然后 再 将 字符串@”ONE” 添加 到数组物件dataArray的第0个物件当中:
|
[mutableStringappendString:@"ONE"];
|
在程序的运行结果当中,你 会注意到 数组物件dataArray 和 它的复制品dataArray2中第一个物件的内容 都改变了。你 也许会理解 为什么数组物件dataArray中第0个物件的内容 会改变,但 不见得能理解 为什么数组物件dataArray的复制品dataArray2中第0个物件的内容 会发生 同样的改变。当你 从一个集合中 获得 一个物件时,你获得的 不是 这个物件的复制品,而是 这个物件的地址。所以 当我们 对dataArray这个物件 采取 objectAtIndex:这项措施
并将 0 作为参数时,我们获得的 是 数组dataArray中第0个物件的地址,而不是 第0个物件的复制品。而 变量mutableString、数组dataArray 和 dataArray2当中第0个元素 都是 同一个物件的地址,所以 改变 一个 就会改变 其余所有的。
既然 数组dataArray2 是 数组dataArray的复制品,而 改变 数组dataArray中第0个物件 就会改变 dataArray2中第0个元素 是 因为我们 对数组dataArray 只进行了 浅层复制。当我们 对数组物件dataArray 采取 mutableCopy这项措施时,新的内存空间 就会分配给 新的数组物件,同时 数组物件dataArray中每个物件的地址 都会复制到 新分配的内存空间内。这 就意味着 我们 只是把 数组物件dataArray中每个物件的地址
从旧的位置 复制 到新的位置,而不是 将 数组物件dataArray中每个物件本身 从旧的位置 复制 到新的位置。
如果 我们 要将 数组物件中每个物件本身 而不是 它们的地址 从旧的位置 复制 到新的位置,那么 我们 必须进行 深层复制。但是 基础框架提供的copy 和 mutableCopy这两项措施 并不能进行 深层复制。在之后 我们 可以了解到 基础框架的归档功能 可以进行 深层复制。
当你 对数组、辞典 或者 集合 进行复制时,你 不但 可能需要将 这些集合中各个成员的地址 从一个地方 复制 到另外一个地方,而且 需要将 这些集合中各个成员本身 从一个地方 复制 到另外一个地方。比如 你 想改变 数组dataArray2中第0个物件 而不想改变 数组dataArray1中第0个物件,那么 你 可以创建 一个新的数组 并且 将 其 存入 数组dataArray2中第0个位置,就像 这样:
|
mutableString=[NSMutableStringstringWithString:[dataArray2objectAtIndex:0]];
[mutableStringappendString:@"ONE"];
[dataArray2replaceObjectAtIndex:0withObject:mutableString];
|
即便 是 这样,变量mutableString 和 数组物件dataArray2第0个元素 依然 存储着 同一个物件的地址,所以 对mutableString做出的改变 也会影响 数组物件dataArray2中的第0个元素。