IOS 关于对象的复制问题
来源:互联网 发布:节假日堵车数据 编辑:程序博客网 时间:2024/06/04 21:53
最近在学习IOS的程序,根据IOS5基础教程编码,在第8章的Search时,提到一个深度复制的概念,后来重新学习了下Objective-C中的copy,mutablecopy,以及其他一些方法,先将相关学习经验记录下来。
XCODE 版本是4.6.3 模拟器是IPHONE6.1,在测试时发现与很多书上,以及网上的资料不符合,不知道是不是苹果新的编译器改动的问题。
1.针对非容器类型
如 NSString,NSMutableString
如果对一不可变对象复制,copy是指针复制(浅拷贝)和mutableCopy就是对象复制
使用mutableCopy复制完后,对象是相互独立;
如下:
NSString *string1=[[NSStringalloc] initWithFormat:@"1111"]; NSString *string2=[string1 copy]; //string2 是string1 的指针复制 NSMutableString *mstring3=[[NSMutableStringalloc] init]; [mstring3 appendString:string1]; // 关于 appendString的使用在后面章节将会介绍,其实这时一个对象复制(深拷贝) NSMutableString *mstring4=[mstring3 mutableCopy]; //使用mutableCopy后 mstring4拥有了和mstring3一样的内容,但是他们所指向的对象时完全不同的 NSLog(@"string1 %@",string1); NSLog(@"string2 %@",string2); NSLog(@"string3 %@",mstring3); NSLog(@"string4 %@",mstring4); [mstring3 appendString:@"22222"]; //通过修改mstring3 ,可以发现因为其使用了 appendString,所以他与string1已经是2个不同的对象了 //因为mstring4使用的是mutableCopy,这也是一个深拷贝,所以mstring4也没有收到影响 NSLog(@"string1 %@",string1); NSLog(@"string2 %@",string2); NSLog(@"string3 %@",mstring3); NSLog(@"string4 %@",mstring4); /* 输出如下: 2013-07-27 20:53:11.818 sections[6371:c07] string1 1111 2013-07-27 20:53:11.819 sections[6371:c07] string2 1111 2013-07-27 20:53:11.819 sections[6371:c07] string3 1111 2013-07-27 20:53:11.819 sections[6371:c07] string4 1111 2013-07-27 20:53:11.819 sections[6371:c07] string1 1111 2013-07-27 20:53:11.820 sections[6371:c07] string2 1111 2013-07-27 20:53:11.820 sections[6371:c07] string3 111122222 2013-07-27 20:53:11.820 sections[6371:c07] string4 1111 */
2. 针对容器下的对象
如NSDictionary,NSMutableDictionary,NSArray,NSMutableArray
NSArray *aKeys=[[NSArrayalloc] initWithObjects:@"key1",@"key2",nil]; NSArray *aValue=[[NSArrayalloc] initWithObjects:@"value1",@"value2",nil]; NSDictionary *tDic=[[NSDictionaryalloc] initWithObjects:aValue forKeys:aKeys]; NSMutableDictionary *mDic1=[tDic mutableCopy]; //一样采用mutablcopy NSLog(@"tDic %@",tDic); NSLog(@"mDic %@",mDic1); [mDic1 setObject:@"mdic1"forKey:@"key1"]; //修改其中一个对象 NSLog(@"tDic %@",tDic); NSLog(@"mDic %@",mDic1);/*2013-07-27 21:09:27.618 sections[6516:c07] tDic { key1 = value1; key2 = value2;}2013-07-27 21:09:27.619 sections[6516:c07] mDic { key1 = value1; key2 = value2;}2013-07-27 21:09:27.619 sections[6516:c07] tDic { key1 = value1; key2 = value2;}2013-07-27 21:09:27.619 sections[6516:c07] mDic { key1 = mdic1; key2 = value2;}*/
mdic的对象已经被改变了,但是tDic的对象仍然和原来一样,说明他们指向的对象是不同的。
3.关于初始化,addObject等对象的复制
NSMutableArray *array1 = [[NSMutableArray alloc] initWithObjects:@"1",@"2",@"3",nil]; NSMutableArray *array2 = [[NSMutableArray alloc] initWithArray:array1]; NSMutableArray *array3 =[[NSMutableArray alloc] init]; [array3 addObjectsFromArray:array1]; NSLog(@"array1 %@",array1); NSLog(@"array2 %@",array2); NSLog(@"array3 %@",array3); [array2 replaceObjectAtIndex:0 withObject:@"100"]; [array3 replaceObjectAtIndex:0 withObject:@"300"]; NSLog(@"array1 %@",array1); NSLog(@"array2 %@",array2); NSLog(@"array3 %@",array3); /* 2013-07-27 20:30:07.681 sections[6203:c07] array1 ( 1, 2, 3 ) 2013-07-27 20:30:07.681 sections[6203:c07] array2 ( 100, 2, 3 ) 2013-07-27 20:30:07.681 sections[6203:c07] array3 ( 300, 2, 3 ) */
结论:使用 mutablecopy,initwithArray addObjectFromArray 都是深层复制,包含非容器,容器在内的对象(容器内的对象)都是被复制的,而不是单纯的指针复制。
4.另外一些对象复制
如果是使用容器进行初始化
NSMutableArray *value1=[[NSMutableArray alloc]initWithObjects:@"V1",@"V2",nil]; NSMutableArray *value2=[[NSMutableArray alloc]initWithObjects:@"VV1",@"VV2",nil]; NSMutableArray *mmkey=[[NSMutableArray alloc]initWithObjects:@"key1",@"key2",nil]; NSMutableArray *mmvalue=[[NSMutableArray alloc]initWithObjects:value1,value2,nil]; NSMutableDictionary *md=[[NSMutableDictionary alloc]initWithObjects:mmvalue forKeys:mmkey]; NSMutableArray *ma=[md valueForKey:@"key1"]; NSLog(@"ma %@",ma); NSLog(@"md %@",md); [ma addObject:@"123"]; [value2 addObject:@"VV3"]; NSLog(@"md %@",md); NSLog(@"ma %@",ma); 2013-07-27 23:30:45.587 sections[7778:c07] ma ( V1, V2)2013-07-27 23:30:45.588 sections[7778:c07] md { key1 = ( V1, V2 ); key2 = ( VV1, VV2 );}2013-07-27 23:30:45.588 sections[7778:c07] md { key1 = ( V1, V2, 123 ); key2 = ( VV1, VV2, VV3 );}2013-07-27 23:30:45.589 sections[7778:c07] ma ( V1, V2, 123)
可以看出
1. 字典在初始化时使用了数组对象,而这个时候是指向这些数组,而不是进行深度拷贝,后面修改了这些数组后,可以看到字典内容也发生了变化。
2. 字典实例调用方法 valueforkey时,实际上依然是一个浅拷贝,修改这个方法返回的对象实例,也会改变字典本身。
另外这里进行一个比较有意思的实验,我们知道NSArray是一个不可变数组,但是如果他是由一个可变的NSMutableString初始化的,那么对于string的修改,是否或影响到Array呢?
NSMutableString *S1=[[NSMutableString alloc]initWithFormat:@"123"]; NSArray *arrayy=[[NSArray alloc]initWithObjects:S1,nil]; NSLog(@"S1 %@",S1); NSLog(@"arrayy %@",arrayy); [S1 appendString:@"321"]; NSLog(@"S1 %@",S1); NSLog(@"arrayy %@",arrayy);2013-07-27 23:38:53.554 sections[7850:c07] S1 1232013-07-27 23:38:53.555 sections[7850:c07] arrayy ( 123)2013-07-27 23:38:53.555 sections[7850:c07] S1 1233212013-07-27 23:38:53.556 sections[7850:c07] arrayy ( 123321)
我想大家一定想到了,肯定会改变。 用C++的思想 可以理解容器类的结构内部都是指针,所谓不可变指的是 const 指针,而指针指向的那个内存的内容是否可变,是根据指针对象的属性决定的。
另外在原书代码中
NSMutableArray *keyArray = [[NSMutableArray alloc] init]; [keyArray addObject:UITableViewIndexSearch]; [keyArray addObjectsFromArray:[[self.allNames allKeys] sortedArrayUsingSelector:@selector(compare:)]]; self.keys = keyArray;
已经很明显的说明 通过addObjectsFromArray的方式获取的数值是一个深度复制的数组,其实可以用同样的方法搞定NSMutableDirectionary,而不需要使用来类别,重新定义一个深度复制的方法。
另外一个需要说明的是,keys是类的一个属性,通过@property定义, 会自动生成其Setkeys的方法,可以使用.的方式进行赋值,但是这种方法调用的是copy,所以 keys和keyarray是指向同一个对象的。
NSMutableArray *tArray=[[NSMutableArray alloc]initWithObjects:@"1",@"2", nil]; self.mKeys=tArray; //使用.的方式赋值,其实是使用copy NSLog(@"tArray %@",tArray); NSLog(@"mKeys %@",self.mKeys); [self.mKeys replaceObjectAtIndex:0 withObject:@"3"]; NSLog(@"tArray %@",tArray); // 这个时候发现tArray的值也被改变了 NSLog(@"mKeys %@",self.mKeys); self.mKeys=[tArray mutableCopy]; //重新使用mutableCopy [self.mKeys replaceObjectAtIndex:0 withObject:@"4"]; NSLog(@"tArray %@",tArray); //tArray的值没有被再次改变,说明他们已经指向了不同对象 NSLog(@"mKeys %@",self.mKeys); 2013-07-27 21:37:44.055 sections[6644:c07] tArray ( 1, 2 ) 2013-07-27 21:37:44.056 sections[6644:c07] mKeys ( 1, 2 ) 2013-07-27 21:37:44.056 sections[6644:c07] tArray ( 3, 2 ) 2013-07-27 21:37:44.056 sections[6644:c07] mKeys ( 3, 2 ) 2013-07-27 21:37:44.056 sections[6644:c07] tArray ( 3, 2 ) 2013-07-27 21:37:44.057 sections[6644:c07] mKeys ( 4, 2 )
、
- IOS 关于对象的复制问题
- IOS对象复制问题
- 关于Java复制对象的问题
- 关于Java复制对象的问题
- 关于对象的构造、复制构造、析构、赋值的问题
- 关于python中对象复制和应用的问题
- 关于对象的深度复制
- 关于复制初始化的问题
- 关于list的复制问题
- iOS 复制UIView所有的对象
- 关于Java中对象的复制
- 关于 Java 中对象的复制
- 关于Flex里面的对象或者ArrayCollection等数组的深度复制问题
- 关于对象的深度复制和浅度复制
- IOS 关于拍照界面,复制,粘贴等菜单的显示为英文的问题
- iOS开发 ----- 关于char *的赋值和字符串之间的复制问题以及sizeof strlen
- iOS之对象复制
- iOS之对象复制
- 统计知识选讲(一)——主成分分析(PCA)的思想
- 优秀程序员不得不知道的20个位运算技巧
- android传感器(sensor)分析(以mma8451重力感应器为基础)
- 无向图的直径以及树的直径
- Visual Studio 2013预览版中的 C++11 新特性
- IOS 关于对象的复制问题
- 告诫自己的话
- POJ2454--Jersey Politics
- 明明是有这个包的,但是导不进去
- 两个View 使用BLOCK传值
- android开发之修改全局自定义字体
- hdu3944(Lucas定理+预处理)
- python创建和解析xml文件
- GitHub上最火的74个Android开源项目