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协议,重写对应的方法,才可使用,要不然会直接崩溃的噢。
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协议,重写对应的方法,才可使用,要不然会直接崩溃的噢。
相关文章推荐
- ios定位开发 当使用百度地图sdk没有启用object c++混编时就会出现如下错误
- 用WaitForSingleObject()函数实现简单的多线程互斥访问
- Object转换为JSON格式字符串
- object-单例设计模式
- [Objective-C] alloc和init要嵌套写而不要分开写
- objective C中的浅复制和深复制
- [Objective-C] isKindOfClass 和 class 方法
- 托管态update更新异常——a different object with the same identifier value was already associated withthe sess
- [Objective-C] 重载objectAtIndexedSubscript和objectForKeyedSubscript方法实现subscripting
- value equality vs. object equality, aliasing, list is mutable DEMO
- Objective-C和 C++ 混编的要点(转)
- div被object覆盖的解决办法
- div被object覆盖的解决办法
- Semaphore Objects
- [Objective-C] selector 简介
- 使用Objective-C的文档生成工具:appledoc
- Object类
- [学习笔记—Objective-C]《Objective-C 程序设计 第6版》第十五章 数字 字符串和集合
- objective c 方法快速查询手册
- Mutex Objects