当前位置: 移动技术网 > 移动技术>移动开发>IOS > iOS深复制与浅复制

iOS深复制与浅复制

2020年08月14日  | 移动技术网移动技术  | 我要评论

概念

浅复制:主要拷贝的是对象的引用值,并没有进行真正的复制,复制的对象和原对象都指向同一个地址。
深复制:主要是将原对象的属性值拷贝过来,而原对象的属性值并不发生变化,复制的对象指向了新的地址。
通俗理解为:浅复制好比你的影子,改变愿对象,复制的对象也会发生变化;而深复制好比克隆人,虽然外貌一样,但却是不同的个体。

应用场景

在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

如对本文有疑问, 点击进行留言回复!!

相关文章:

验证码:
移动技术网