iOS深复制与浅复制
iOS深浅复制
概念
浅复制:主要拷贝的是对象的引用值,并没有进行真正的复制,复制的对象和原对象都指向同一个地址。
深复制:主要是将原对象的属性值拷贝过来,而原对象的属性值并不发生变化,复制的对象指向了新的地址。
通俗理解为:浅复制好比你的影子,改变愿对象,复制的对象也会发生变化;而深复制好比克隆人,虽然外貌一样,但却是不同的个体。
应用场景
在iOS里,copy与mutableCopy都是NSObject里的方法,一个NSObject的对象要想使用这两个函数,那么类必须实现NSCopying协议或NSMutableCopying协议
集合类对象和非集合类对象
非集合类对象的copy与mutableCopy
不可变对象的copy方法是浅复制,mutableCopy方法是深复制;
可变对象的copy和mutableCopy方法都是深复制;
无论是可变对象还是不可变对象,copy方法返回的对象是不可变对象。
//非集合类不可变对象的copy和mutablecopy
//浅复制
NSString *stringcopy = @"hello,world";
NSString *copy_string = [stringcopy copy];
NSLog(@"string = %p",stringcopy);
NSLog(@"copy_string = %p",copy_string);
NSLog(@"");
//深复制
NSString *stringcopy2 = @"hello,world";
NSMutableString *copy_string2 = [stringcopy mutableCopy];
NSLog(@"string2 = %p",stringcopy2);
NSLog(@"copy_string2 = %p",copy_string2);
NSLog(@"");
//非集合类可变对象的copy和mutablecopy
//深复制
NSMutableString *mutablestring = [[NSMutableString alloc] init];
[mutablestring appendString:@"hello"];
NSString *mutable_string = [mutablestring copy];
NSLog(@"mutablestring = %p",mutablestring);
NSLog(@"mutable_string = %p",mutable_string);
NSLog(@"");
//深复制
NSMutableString *mutablestring2 = [[NSMutableString alloc] init];
[mutablestring2 appendString:@"hello"];
NSMutableString *mutable_string2 = [mutablestring mutableCopy];
NSLog(@"mutablestring2 = %p",mutablestring2);
NSLog(@"mutable_string2 = %p",mutable_string2);
NSLog(@"");
//代码结果
string = 0x10dacc020
copy_string = 0x10dacc020
string2 = 0x10dacc020
copy_string2 = 0x6000003486c0
mutablestring = 0x6000003029d0
mutable_string = 0xcbbcdfa34e0a2222
mutablestring2 = 0x600000366490
mutable_string2 = 0x600000366790
集合类对象的copy与mutableCopy
集合类对象是指NSArray、NSDictionary … 之类的对象,集合对象与非集合对象所遵循的规则基本上是一样的(但是:集合对象的内容拷贝仅限于对象本身,对象元素仍然是指针拷贝,也就是说:集合对象的深复制并不是严格意义上的深复制,而是单层深复制)
,当我们对集合类对象进行mutableCopy操作时,虽然数组内存地址发生了变化,但是数组元素的内存地址并没有发生变化这个就是单层深复制。
//集合类不可变对象的copy和mutablecopy
//copy-浅复制
NSArray *imarray = @[@"apple"];
NSArray *copy_imarray = [imarray copy];
NSLog(@"imarray = %p", imarray);
NSLog(@"copy_imarray = %p", copy_imarray);
NSLog(@"");
//mutablecopy-深复制
NSArray *imarray2 = @[@"apple"];
NSMutableArray *copy_imarray2 = [imarray mutableCopy];
NSLog(@"imarray2 = %p", imarray2);
NSLog(@"copy_imarray2 = %p", copy_imarray2);
NSLog(@"");
//集合类可变对象的copy和mutablecopy
//copy--深复制
NSMutableArray *mutablearray = [[NSMutableArray alloc] init];
[mutablearray addObject:@"apple"];
[mutablearray addObject:@"banana"];
[mutablearray addObject:@"melon"];
NSArray *copy_mutablearray = [mutablearray copy];
NSLog(@"mutablearray = %p", mutablearray);
NSLog(@"copy_murablearray = %p", copy_mutablearray);
NSLog(@"");
//mutablecopy--单层深复制
NSMutableArray *mutablearray2 = [[NSMutableArray alloc] init];
[mutablearray2 addObject:@"apple"];
[mutablearray2 addObject:@"banana"];
[mutablearray2 addObject:@"melon"];
NSMutableArray *copy_mutablearray2 = [mutablearray mutableCopy];
NSLog(@"mutablearray2 = %p", mutablearray2);
NSLog(@"copy_murablearray2 = %p", copy_mutablearray2);
//实例结果如下
imarray = 0x60000262c7c0
copy_imarray = 0x60000262c7c0
imarray2 = 0x600002638950
copy_imarray2 = 0x600002a558c0
mutablearray = 0x600002a3f480
copy_murablearray = 0x600002a3f270
mutablearray2 = 0x600002a55c80
copy_murablearray2 = 0x600002a55b00
单层深复制和完全深复制
单层深复制:对集合对象来说,深复制时只是将第一层对象进行了深复制,内部的对象仍然是浅复制,也就是内层仍然进行的是指针复制。
(如何判断:将内部元素的地址打印出来,看是否为指针复制)
完全深复制:对于被复制对象来说,每一层都是内容复制。
单层复制代码示例:
NSMutableArray *mutablearray2 = [[NSMutableArray alloc] init];
[mutablearray2 addObject:@"apple"];
[mutablearray2 addObject:@"banana"];
[mutablearray2 addObject:@"melon"];
NSMutableArray *copy_mutablearray2 = [mutablearray mutableCopy];
NSLog(@"mutablearray2 = %p", mutablearray2);
NSLog(@"copy_murablearray2 = %p", copy_mutablearray2);
NSLog(@"第一层 = %p", mutablearray2[0]);
NSLog(@"第一层复制 = %p", copy_mutablearray2[0]);
//实例结果如下
mutablearray2 = 0x60000344eeb0
copy_murablearray2 = 0x60000344ec70
第一层 = 0x101ccc020
第一层复制 = 0x101ccc020
若想对多层集合进行深复制,则需要用到协议方法或者归档解档
完全深复制的实现
1、使用协议方法
使用 initWith***: copyItems:YES 方法
自定义集合对象使用这个方法,对象必须遵守NSCopying协议,并重写- (id)copyWithZone:(NSZone *)zone方法。(系统类方法已经实现)。
代码如下
#import <Foundation/Foundation.h>
@interface ModelStudent : NSObject<NSCopying>
@property(nonatomic, copy) NSString * name;
@property(nonatomic, assign) NSInteger age;
@property(nonatomic, assign) NSInteger sex;
@end
#import "ModelStudent.h"
@implementation ModelStudent
- (id)copyWithZone:(NSZone *)zone{
ModelStudent * s = [[ModelStudent alloc]init];
s.name = self.name;
s.age = self.age;
s.sex = self.sex;
return s;
}
@end
ModelStudent * model1 = [ModelStudent new];
model1.name = @"mao";
model1.age = 14;
ModelStudent * model2 = [ModelStudent new];
model2.name = @"mao";
model2.age = 14;
self.arr = @[model1, model2];
//完全深复制
NSArray * array4 = [[NSArray alloc]initWithArray:self.arr copyItems:YES];
NSLog(@"%@,%@", self.arr, array4);
实例结果如下
array (
"<ModelStudent: 0x600000fb1220>",
"<ModelStudent: 0x600000fb1260>"
)
copy array (
"<ModelStudent: 0x600000fb11e0>",
"<ModelStudent: 0x600000fb12a0>"
)
可以看到,数组地址不同,数组中元素地址也不相同,说明已经实现了完全深复制,但是协议方法是适用于单层数组,如果是多层数组,则需要使用归档解档的方法
2、归档解档
使用NSKeyedArchiver压缩对象成二进制数据,再使用NSKeyedUnarchiver解压二进制数据。通常我们对模型数组完全复制,先将模型数组转换为data数组,再将data数组转换为模型数组
ModelStudent *student1 = [[ModelStudent alloc] init];
student1.name = @"111";
student1.age = 10;
student1.sex = 1;
ModelStudent *student2 = [[ModelStudent alloc] init];
student2.name = @"222";
student2.age = 20;
student2.sex = 0;
self.array = @[student1, student2];
NSMutableArray *manyArray = [NSMutableArray arrayWithObjects:_array, @"123", nil];
NSMutableArray *copyArray = [NSKeyedUnarchiver unarchiveObjectWithData:[NSKeyedArchiver archivedDataWithRootObject:manyArray requiringSecureCoding:NO error:nil] ];
manyArray (
(
"<ModelStudent: 0x600003905640>",
"<ModelStudent: 0x6000039054a0>"
),
123
)
copy array (
(
"<ModelStudent: 0x600003905840>",
"<ModelStudent: 0x600003905880>"
),
123
)
本文地址:https://blog.csdn.net/weixin_45708424/article/details/107944266