文章目录
- 系统的非容器类对象
- 非容器类对象的深浅拷贝
- NSString对象
- NSMutableString 对象
- 系统容器类对象
- 容器的深浅拷贝
- 容器的对象的深浅拷贝
- 对容器元素实现真正的深拷贝
- 大大的待解决的疑惑
- 旧版本归档解档的复制
- iOS提供了copy和mutablecopy方法,顾名思义,copy就是复制了一个imutable的对象,而mutablecopy就是复制了一个mutable的对象。以下将举几个例子来说明。
系统的非容器类对象
- 对于系统的非容器类对象就是NSString和NSNumber这一类的总称。
非容器类对象的深浅拷贝
NSString对象
- 举个例子
NSString *string1 = @"hello iOS";
NSString *string2 = [string1 copy];
NSString *string3 = [string1 mutableCopy];
NSMutableString *string4 = [string1 copy];
NSMutableString *string5 = [string1 mutableCopy];
- 打印地址
NSLog(@"string1 = %p",string1);
NSLog(@"string2 = %p",string2);
NSLog(@"string3 = %p",string3);
NSLog(@"string4 = %p",string4);
NSLog(@"string5 = %p",string5);
- iOS讲义上是这样解释的:copy方法返回的对象的不可变对象,而mutableCopy方法返回的对象是可变对象。,对于上述的s1 , s2返回的是同一个不可变的对象,意思就是只是复制了内容而没有改变地址,被复制对象与复制对象都是不可变的,因此浅复制
- 对于S4 mutable obj(对象) + copy : 防止被复制对象的修改对复制对象的影响,返回对象是immutable!,S4的地址和S1也是一样的,我理解为浅复制(Copy的原理)
- 对于S3:immutable obj +mutableCopy 因为返回对象是mutable,为了防止复制对象的数据修改对被复制对象的影响,采用深复制。
- 对于S5:而string5 则是我们所说的真正意义上的复制:mutable obj + mutableCopy 防止互相影响 系统为其分配了新内存,但指针所指向的字符串还是和string1所指的一样
NSMutableString 对象
NSMutableString *string1 = [NSMutableString stringWithString:@"helloworld"];
NSString *string2 = [string1 copy];
NSString *string3 = [string1 mutableCopy];
NSMutableString *string4 = [string1 copy];
NSMutableString *string5 = [string1 mutableCopy];
NSLog(@"string1 = %p",string1);
NSLog(@"string2 = %p",string2);
NSLog(@"string3 = %p",string3);
NSLog(@"string4 = %p",string4);
NSLog(@"string5 = %p",string5);
- 分析
- 对于以上四个NSString对象所分配的内存都是不一样的
- 对于系统的非容器类对象,我们可以认为,如果对一不可变对象复制,copy是指针复制(浅拷贝)和mutableCopy就是对象复制(深拷贝)。如果是对可变对象复制,都是深拷贝,但是copy返回的对象是不可变的。
系统容器类对象
- 系统的容器类对象指NSArray,NSDictionary等
- 这里用NSArray作为例子
容器的深浅拷贝
- 举个例子
NSArray *array01 = [NSArray arrayWithObjects:@"a", @"b", @"c", nil];
NSArray *copyArray01 = [array01 copy];
NSMutableArray *mutableCopyArray01 = [array01 mutableCopy];
NSLog(@"array01 = %p", array01);
NSLog(@"copyArray01 = %p", copyArray01);
NSLog(@"mutableCopyArray01 = %p", mutableCopyArray01);
- 通过对比发现,容器的深浅拷贝和上述非容器的深浅拷贝作用是一样的,对于容器类本身,上面讨论的结论也是适用的,需要探讨的是复制后容器内对象的变化。
- copy返回不可变对象,mutablecopy返回可变对象
- copyArray01是和array01同一个NSArray对象(指向相同的对象),包括array里面的元素也是指向相同的指针
- mutableCopyArray01是array01的可变副本,指向的对象和array1不同,但是其中的元素和array1中的元素指向的是同一个对象。mutableCopyArray01还可以修改自己的对象
容器的对象的深浅拷贝
array01和copyArray01是指针复制,而mutableCopyArray01是对象复制,mutableCopyArray01还可以改变期内的元素:删除或添加。注意:容器内的元素内容都是指针复制。
NSMutableArray *mutableArray01 = [NSMutableArray arrayWithObjects:@"a",@"b",@"c", nil];
NSArray *copyArray01 = [mutableArray01 copy];
NSMutableArray *mutableCopyArray01 = [mutableArray01 mutableCopy];
//对比容器的地址,看容器类是否是不同的对象
NSLog(@"mutableArray01 = %p", mutableArray01);
NSLog(@"copyArray01 = %p", copyArray01);
NSLog(@"mutableCopyArray01 = %p", mutableCopyArray01);
// 打印复制后的数组的内容
[mutableArray01 addObject:@"d"];
NSLog(@"mutableArray01 = %@", mutableArray01);
NSLog(@"copyArray01 = %@", copyArray01);
NSLog(@"mutableCopyArray01 = %@", mutableCopyArray01);
// 对比容器的元素是否是同一对象,发现地址一样,如下图所示,说明容器的对象复制只是简单的指针复制
NSLog(@"mutableArray01[0] = %p", mutableArray01[1]);
NSLog(@"copyArray01[0] = %p", copyArray01[1]);
NSLog(@"mutableCopyArray01[0] = %p", mutableCopyArray01[1]);
- 打印地址
- 把元素的地址单独拿出来看
- 虽然三个数组指向的对象都是不一样的对象,但是程序的数组的元素地址都是一样的。
- 由此可见,对于容器而言,其元素对象始终是指针复制。
对容器元素实现真正的深拷贝
Apple官方文档:深浅拷贝
大大的待解决的疑惑
类似于解档 归档 的深浅拷贝,这边有点疑惑。
网上参考到了最新的解档 归档 但是解 归后
trueDeepCopyArray 内容已经没有了
NSArray* array = [NSArray arrayWithObjects:[NSMutableString stringWithString:@"frist"], [NSString stringWithFormat:@"b"], @"c", nil];
NSArray* deepCopyArray = [[NSArray alloc] initWithArray:array copyItems:YES];
NSArray* trueDeepCopyArray = [NSKeyedUnarchiver unarchivedObjectOfClass:[NSArray class] fromData:[NSKeyedArchiver archivedDataWithRootObject:array requiringSecureCoding:NO error:nil] error:nil];
NSLog(@"array = %p", array);
NSLog(@"deepCopyArray = %p", deepCopyArray);
NSLog(@"trueDeepCopyArray = %p", trueDeepCopyArray);
NSLog(@"array = %@", array);
NSLog(@"deepCopyArray = %@", deepCopyArray);
NSLog(@"trueDeepCopyArray = %@", trueDeepCopyArray);
NSLog(@"array[1] = %p", array[1]);
NSLog(@" deepCopyArray[1] = %p", deepCopyArray[1]);
NSLog(@"trueDeepCopyArray[1] = %p", trueDeepCopyArray[1]);
- 复制结果
trueDeepCopyArray = (null) 待解决
iOS 已经弃用的归档解档 可以复制但是三个容器的对象的地址还是一样的
参考博客 iOS深浅复制
旧版本归档解档的复制
- 注意声明的 解档 归档是针对trueDeepCopyArray 的
NSArray* array = [NSArray arrayWithObjects:[NSMutableString stringWithString:@"frist"], [NSString stringWithFormat:@"b"], @"c", nil];
NSArray* deepCopyArray = [[NSArray alloc] initWithArray:array copyItems:YES];
NSArray* trueDeepCopyArray = [NSKeyedUnarchiver unarchiveObjectWithData:[NSKeyedArchiver archivedDataWithRootObject:array]];
NSLog(@"array = %p", array);
NSLog(@"deepCopyArray = %p", deepCopyArray);
NSLog(@"trueDeepCopyArray = %p", trueDeepCopyArray);
NSLog(@"array = %@", array);
NSLog(@"deepCopyArray = %@", deepCopyArray);
NSLog(@"trueDeepCopyArray = %@", trueDeepCopyArray);
NSLog(@"array[1] = %p", array[1]);
NSLog(@" deepCopyArray[1] = %p", deepCopyArray[1]);
NSLog(@"trueDeepCopyArray[1] = %p", trueDeepCopyArray[1]);