在iOS开发中,对于copy和mutableCopy都不陌生。如果您不知道它们之间区别的话,看完本文我相信您肯定会分的很清楚。接下来,就通过几个小例子来了解一下吧。 NO.1 NSArray * array = [[NSArray alloc] initWithObjects:@"sogouqa", nil]; NSArray * retainArray = array; NSArray * copyArray = [array copy]; NSArray * mutableCopyArray = [array mutableCopy]; NSLog(@"%d\t%p\t%p", _objc_rootRetainCount(array), &array, array); NSLog(@"%d\t%p\t%p", _objc_rootRetainCount(retainArray), &retainArray, retainArray); NSLog(@"%d\t%p\t%p", _objc_rootRetainCount(copyArray), ©Array, copyArray); NSLog(@"%d\t%p\t%p", _objc_rootRetainCount(mutableCopyArray), &mutableCopyArray, mutableCopyArray); 这个是在ARC下很简单的小例子,首先初始化一个数组array,然后做了下赋值操作,接着做了copy和mutableCopy操作。后面的就是打印一些信息,_objc_rootRetainCount()函数是在ARC下打印对象的retainCount。后面两个信息也就是指针的地址和指针指向的对象的地址。通过retainCount和指针指向的地址,可以判断出来那些对象指的是同一块地址。结果如下: 3 0x7fff5fbff7a8 0x100306960 3 0x7fff5fbff7a0 0x100306960 3 0x7fff5fbff798 0x100306960 1 0x7fff5fbff790 0x100306a00 接下来我们来分析下结果,首先执行完以上操作以后,array、retainArray、copyArray的retainCount都是3,而且他们指向的地址都是0x100306960。这也就是说明他们指向的是同一块内存地址。所以NSArray调用copy函数,是浅拷贝,copyArray指针和array指针本身不是同一个地址,但是他们指向的空间是相同的。对于上面这个例子来说,NSArray调用直接赋值,和调用copy进行赋值,结果是完全一致的,都是浅拷贝。而mutableCopy,很明显是深拷贝,因为mutableCopyArray和array指向的地址不一样。针对上面的例子,我们可以得出: NSArray的copy函数是浅拷贝,mutableCopy函数是深拷贝。 接下来我们继续做实验,把上面例子所有的NSArray,都替换成NSMutableArray,调用的函数全不变,那么结果会是什么样子? NO.2 NSMutableArray * array = [[NSMutableArray alloc] initWithObjects:@"sogouqa", nil]; NSMutableArray * retainArray = array; NSMutableArray * copyArray = [array copy]; NSMutableArray * mutableCopyArray = [array mutableCopy]; NSLog(@"%d\t%p\t%p", _objc_rootRetainCount(array), &array, array); NSLog(@"%d\t%p\t%p", _objc_rootRetainCount(retainArray), &retainArray, retainArray); NSLog(@"%d\t%p\t%p", _objc_rootRetainCount(copyArray), ©Array, copyArray); NSLog(@"%d\t%p\t%p", _objc_rootRetainCount(mutableCopyArray), &mutableCopyArray, mutableCopyArray); 这次输入应该是什么样子的: 2 0x7fff5fbff7a8 0x1002069d0 2 0x7fff5fbff7a0 0x1002069d0 1 0x7fff5fbff798 0x1002074f0 1 0x7fff5fbff790 0x100207510 从结果上看,跟之前的结构略有不同,普通赋值retainArray和array指向的是同一块内存地址,retainCount为2,显然是浅拷贝。但是调用copy和mutableCopy函数,指针指向的地址不同,那说明: NSMutableArray调用copy和mutableCopy都是深拷贝。 但是调用copy和mutableCopy有什么区别呢?别着急,我们接着往下看。接着上一个例子,我们来打印一下各个对象的类型: NO.3 NSMutableArray * array = [[NSMutableArray alloc] initWithObjects:@"sogouqa", nil]; NSMutableArray * copyArray = [array copy]; NSMutableArray * mutableCopyArray = [array mutableCopy]; NSLog(@"array class = %@", [array className]); NSLog(@"copyArray Class = %@", [copyArray className]); NSLog(@"mutableCopyArray = %@", [mutableCopyArray className]); 结果: array class = __NSArrayM copyArray Class = __NSArrayI mutableCopyArray = __NSArrayM 我们可以看到copyArray是_NSArrayI,说明是Immutable Array,也就是普通的NSArray类型,mutableCopyArray是_NSArrayM,也就是NSMutableArray类型。那么接下来我们看下NSArray调用copy和mutableCopy都生成什么类型的对象。 NO.4 NSArray * array = [[NSArray alloc] initWithObjects:@"sogouqa", nil]; NSArray * copyArray = [array copy]; NSArray * mutableCopyArray = [array mutableCopy]; NSLog(@"array class = %@", [array className]); NSLog(@"copyArray Class = %@", [copyArray className]); NSLog(@"mutableCopyArray = %@", [mutableCopyArray className]); 结果: array class = __NSArrayI copyArray Class = __NSArrayI mutableCopyArray = __NSArrayM 结果显示,NSArray调用copy生成的是NSArray对象,调用mutableCopy生成的是NSMutableArray对象。 总结 1. NSArray调用copy,是浅拷贝,生成的是NSArray对象; 2. NSArray调用mutableCopy,是深拷贝,生成的是NSMutableArray对象; 3. NSMutableArray调用copy,是深拷贝,生成的是NSArray对象; 4. NSMutableArray调用mutableCopy,是深拷贝,生成的是NSMutableArray对象。 PS:这个理论也适用于Foundation框架里面的其他对象,例如string,dictionary等。如果自定义的类需要使用copy或mutableCopy函数的话,就要事先实现好NSCopying或NSMutableCopying协议,重写对应的方法,才可使用,要不然会直接崩溃的噢。