欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  移动技术

iOS深复制与浅复制

程序员文章站 2022-05-02 23:46:41
iOS深浅复制概念应用场景集合类对象和非集合类对象单层深复制和完全深复制完全深复制的实现概念浅复制:主要拷贝的是对象的引用值,并没有进行真正的复制,复制的对象和原对象都指向同一个地址。深复制:主要是将原对象的属性值拷贝过来,而原对象的属性值并不发生变化,复制的对象指向了新的地址,深拷贝和浅拷贝的本质是地址是否相同通俗理解为:浅拷贝好比你的影子;而深拷贝好比克隆人,(这里加一个图片,就是关于深复制和浅复制是地址的重新分配)应用场景在iOS里,copy与mutableCopy都是NSObject里...

概念

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

应用场景

在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