您的位置:首页 > 移动开发 > Objective-C

Objective-C中Copy和MutableCopy,你了解多少?

2015-07-09 15:23 447 查看
在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协议,重写对应的方法,才可使用,要不然会直接崩溃的噢。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: