关于copy和mutableCopy的内容多了一些,所以分开两部分写了,上一篇写到的是非容器类的copy和mutableCopy,这篇主要看容器类的copy和mutableCopy。
二、容器类的浅拷贝和深拷贝
容器类主要是指NSArray和NSMutableArray,NSDictionary和NSMutableDictionary等,这部分的拷贝其实和非容器类的有些相似,不同的地方在于容器内对象的拷贝。
2.1 不可变对象的浅拷贝和深拷贝
NSArray *array = [NSArray arrayWithObjects:@"a", @"b", @"c", @"d", nil];
NSArray *arrayCopy = [array copy];
NSArray *arrayMCopy = [array mutableCopy];
NSMutableArray *marryCopy = [array copy];
NSMutableArray *marrayMCopy = [array mutableCopy];
NSLog(@"array--------%p",array);
NSLog(@"arrayCopy----%p",arrayCopy);
NSLog(@"arrayMCopy---%p",arrayMCopy);
NSLog(@"marryCopy----%p",marryCopy);
NSLog(@"marrayMCopy--%p",marrayMCopy);
2015-09-21 10:34:05.725 CopyAndMutableCopyTest[643:34782] array--------0x1002069c0
2015-09-21 10:34:05.726 CopyAndMutableCopyTest[643:34782] arrayCopy----0x1002069c0
2015-09-21 10:34:05.726 CopyAndMutableCopyTest[643:34782] arrayMCopy---0x100207e80
2015-09-21 10:34:05.726 CopyAndMutableCopyTest[643:34782] marryCopy----0x1002069c0
2015-09-21 10:34:05.727 CopyAndMutableCopyTest[643:34782] marrayMCopy--0x100207ed0
可以看到,对于不可变对象array的拷贝,效果和非容器类的不可变对象一样。
array、arrayCopy和arrayMCopy的内存地址是一样的,说明了[array copy]对array进行了一次浅拷贝,即指针复制,然后赋值给arrayCopy 和arrayMCopy,这两个指针指向的地址是同一个对象。
而marrayCopy和marrayMCopy的地址则和array的地址不同,说明他们是不同的对象,[array mutableCopy]对array进行了一次深拷贝,在内存中开辟一块存储区域用于存放新的对象。
但是要注意,不管对array进行的是copy还是mutableCopy,容器类对象array中的对象都只进行指针复制(浅拷贝)。这里如果不懂,看下面的例子就可以明白了。
2.2 可变对象的浅拷贝和深拷贝
NSMutableArray *array = [NSMutableArray arrayWithObjects:[NSMutableString stringWithString:@"a"], @"b", @"c", @"d", nil];
NSArray *arrayCopy = [array copy];
NSArray *arrayMCopy = [array mutableCopy];
NSMutableArray *marrayCopy = [array copy];
NSMutableArray *marrayMCopy = [array mutableCopy];
//打印所有测试对象
NSLog(@"array--%@", array);
NSLog(@"arrayCopy--%@", arrayCopy);
NSLog(@"arrayMCopy--%@", arrayMCopy);
NSLog(@"marrayCopy--%@", marrayCopy);
NSLog(@"marrayMCopy--%@", marrayMCopy);
2015-09-21 10:50:01.954 CopyAndMutableCopyTest[667:40305] array--(a,b,c,d)
2015-09-21 10:50:01.955 CopyAndMutableCopyTest[667:40305] arrayCopy--(a,b,c,d)
2015-09-21 10:50:01.955 CopyAndMutableCopyTest[667:40305] arrayMCopy--(a,b,c,d)
2015-09-21 10:50:01.955 CopyAndMutableCopyTest[667:40305] marrayCopy--(a,b,c,d)
2015-09-21 10:50:01.955 CopyAndMutableCopyTest[667:40305] marrayMCopy--(a,b,c,d)
//追加array中的第一个可变对象NSMutableString
NSMutableString *testString = [array objectAtIndex:0];
[testString appendString:@"tail"];
//打印所有测试对象
NSLog(@"array--%@", array);
NSLog(@"arrayCopy--%@", arrayCopy);
NSLog(@"arrayMCopy--%@", arrayMCopy);
NSLog(@"marrayCopy--%@", marrayCopy);
NSLog(@"marrayMCopy--%@", marrayMCopy);
2015-09-21 10:50:01.956 CopyAndMutableCopyTest[667:40305] array--(atail,b,c,d)
2015-09-21 10:50:01.956 CopyAndMutableCopyTest[667:40305] arrayCopy--(atail,b,c,d)
2015-09-21 10:50:01.956 CopyAndMutableCopyTest[667:40305] arrayMCopy--(atail,b,c,d)
2015-09-21 10:50:01.956 CopyAndMutableCopyTest[667:40305] marrayCopy--(atail,b,c,d)
2015-09-21 10:50:01.956 CopyAndMutableCopyTest[667:40305] marrayMCopy--(atail,b,c,d)
//打印所有测试对象的地址
NSLog(@"array--------%p",array);
NSLog(@"arrayCopy----%p",arrayCopy);
NSLog(@"arrayMCopy---%p",arrayMCopy);
NSLog(@"marryCopy----%p",marrayCopy);
NSLog(@"marrayMCopy--%p",marrayMCopy);
2015-09-21 10:50:01.956 CopyAndMutableCopyTest[667:40305] array--------0x100206da0
2015-09-21 10:50:01.956 CopyAndMutableCopyTest[667:40305] arrayCopy----0x100206fa0
2015-09-21 10:50:01.956 CopyAndMutableCopyTest[667:40305] arrayMCopy---0x100207a30
2015-09-21 10:50:01.974 CopyAndMutableCopyTest[667:40305] marryCopy----0x100207a80
2015-09-21 10:50:01.974 CopyAndMutableCopyTest[667:40305] marrayMCopy--0x100207ab0
可以看到每个对象的地址都不一样
2015-09-21 10:50:01.956 CopyAndMutableCopyTest[667:40305] array--------0x100206da0
2015-09-21 10:50:01.956 CopyAndMutableCopyTest[667:40305] arrayCopy----0x100206fa0
2015-09-21 10:50:01.956 CopyAndMutableCopyTest[667:40305] arrayMCopy---0x100207a30
2015-09-21 10:50:01.974 CopyAndMutableCopyTest[667:40305] marryCopy----0x100207a80
2015-09-21 10:50:01.974 CopyAndMutableCopyTest[667:40305] marrayMCopy--0x100207ab0
所以如果是对可变对象array进行的拷贝,则不论是对array进行了mutableCopy还是copy,都会产生新的内存地址,所以这时的拷贝都是深拷贝。
但是!这时候数组包含的对象只进行了指针复制。看代码中的例子,如果我讲array中的第一个可变对象[NSMutableString stringWithString:@"a"]
取出放到testString中来,并追加一个tail
//追加array中的第一个可变对象NSMutableString
NSMutableString *testString = [array objectAtIndex:0];
[testString appendString:@"tail"];
那么array中的第一个可变对象的内容就会变成atail。
而根据指针复制的特点(如果还不清楚的请看第一篇),因为arrayCopy、arrayMCopy、marryCopy、marrayMCopy里面的第一个对象都指向同一个地址,所以其内容也会跟着改变,这些arrayCopy、arrayMCopy、marryCopy、marrayMCopy数组的第一个对象都会变成atail。
这就是数组包含的对象是指针复制的解释。