iOS-容器类的深浅拷贝和完全拷贝

  • 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]);
        

请添加图片描述

  • 3
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值