转载

iOS开发之Copy/MutableCopy

概述

在OC语法中,提供了Copy语法(Copy/MutableCopy)用于对象的拷贝。其中很容易混淆的是浅拷贝和深拷贝。所谓浅拷贝,即单纯的地址拷贝,并不产生新的对象,而是对原对象的引用计数值加1;而深拷贝,即是对象拷贝,产生新的对象副本,拥有独立的内存空间,引用计数器为1。

我们通过一张图先来看看深拷贝与浅拷贝的区别:

iOS开发之Copy/MutableCopy

目录

  1. 系统类对象Copy/NSMutableCopy
    • 1.1mutableCopy不一定是深拷贝
  2. 自定义对象Copy/NSMutableCopy
    • 2.1Copy需要遵守NSCopying协议,重写+copyWithZone
    • 2.2NSMutableCopy需要遵守NSMutableCopying协议,重写+mutableCopyWithZone

一、系统类对象Copy/NSMutableCopy

我们常用的有NSString/NSMutableString、NSArray/NSMutableArray、NSDictionary/NSMutableDictionary、NSSet、NSMutableSet等系统类对象,下面我们来验证什么情况下是深拷贝,什么情况下是浅拷贝。

1.1 mutableCopy不一定是深拷贝

1.1.1 先来测试一下NSString与NSMutableString:

  NSString *str1 = @"str1"; NSMutableString *str2 = [str1mutableCopy]; NSLog(@"str1=%p str2=%p", str1, str2);    NSMutableString *str3 = [[NSMutableString alloc]initWithString:@"sdfsdf"];; NSMutableString *str4 = [str1mutableCopy]; NSLog(@"str3=%p str4=%p", str3, str4);   // 打印结果: // str1=0x10516e068 str2=0x7fdd73425bd0 // str3=0x7fdd7373d360 str4=0x7fdd7373a190   

从打印结果可以看出来,对于NSString与NSMutableString的mutableCopy:

  • NSString类型对象调用mutableCopy得到的新对象,拥有独立的内存空间,因此是深拷贝
  • NSMutableString类型对象调用mutableCopy得到的新对象,拥有独立的内存空间,因此是深拷贝

1.1.2测试NSArray/NSMutableArray的情况如何

  NSArray *array = @[@"array", @"array1"]; NSMutableArray *array1 = [arraymutableCopy]; NSLog(@"array=%p, array1=%p", array, array1);    for (id objin array) {     NSLog(@"%p", obj); }    for (id objin array1) {     NSLog(@"%p", obj); }   // 打印结果: array=0x7fdf196055c0, array1=0x7fdf19695fa0   0x105a66088 0x105a660a8   0x105a66088 0x105a660a8   

由此可以知道,NSArray对象调用mutableCopy会重新新的可变数组对象,但是可变数组对象的元素并没有独立的内存空间,只是地址的复制而已,因此只是对数组进行了深拷贝,而对数组元素却是进行浅拷贝。这种情况叫做集合的单层深复制 (One-Level-Deep Copy)。

1.1.3 测试NSDictionary/NSMutableDictionary

  NSDictionary *dict = @{@"key"  : @"value",                       @"key1" : @"value1"}; NSMutableDictionary *dict1 = [dictmutableCopy]; NSLog(@"dict=%p, dict1=%p", dict, dict1);   for (id objin dict.allValues) {   NSLog(@"%p", obj); }   for (id objin dict1.allValues) {   NSLog(@"%p", obj); }   // 打印结果: dict=0x7f9e70c3a0b0, dict1=0x7f9e70c2f100   0x1021f40a0 0x1021f40e0   0x1021f40a0 0x1021f40e0   

从打印结果可以看出来这是NSArray/NSMutableArray的情况是一样的,因此对于NSSet/NSMutableSet自然也是一样的,它们都属于集合类型。

1.2 copy不一定是浅拷贝

我们来考虑NSString/NSMutableString之间的互相拷贝情况:

  1. NSString对象copy得到NSString对象
  2. NSMutableString对象copy得到NSString对象

1.2.1 NSString对象copy得到NSString对象

  NSString *str = @"标哥的技术博客"; // 因为NSString对象本身就不可变,所以并没产生新的对象,而是返回对象本身,但是引用计数加1 NSString *str2 = [strcopy];      // 输出二者的地址,二者的地址是相同的 NSLog(@"str --> %p",str); NSLog(@"str2 --> %p",str2);   // 打印结果: str --> 0x10c820068 str2 --> 0x10c820068   

从打印结果可以看到地址是一样的,因此它并没有做深拷贝,而是浅拷贝。

1.2.2 NSMutableString对象copy得到NSString对象

  NSMutableString *str = [[NSMutableString alloc]initWithString:@"标哥的技术博客"]; NSString *str2 = [strcopy]; NSLog(@"str --> %p",str); NSLog(@"str2 --> %p",str2);   // 打印结果: str --> 0x7f9393e0fa90 str2 --> 0x7f9393e7cc10   

从打印结果可以看到两个地址不一样,说明发生的是深拷贝。

二、自定义对象Copy/NSMutableCopy

对于自定义的对象,默认是不遵守NSCopying/NSMutableCopying协议的,如果我们希望自定义对象可以调用copy/mutableCopy,则需要手动去实现。

2.1 Copy需要遵守NSCopying协议,重写+copyWithZone

  @interfaceBlog: NSObject<NSCopying>   @property (nonatomic, copy) NSString *name; @property (nonatomic, copy) NSString *version;   @end     @implementation Blog   // 重写它 - (id)copyWithZone:(NSZone *)zone {   Blog *blog = [[Blog alloc]init];   blog.name = self.name;   blog.version = self.version;      return blog; }   @end   

测试来测试一下是否可以正常调用copy:

  Blog *blog = [[Blog alloc]init]; blog.name = @"标哥的技术博客"; blog.version = @"v1.0.0";    Blog *anotherBlog = [blogcopy]; NSLog(@"blog=%p, anotherBlog=%p", blog, anotherBlog);   // blog=0x7ffd13499f50, anotherBlog=0x7ffd1348f3a0   

可以正常使用了!调用copy是生成新的对象!

2.1 NSMutableCopy需要遵守NSMutableCopying协议,重写+mutableCopyWithZone

似乎没有见过自定义的遵守NSMutableCopying协议的类型,因为对于可变操作通常是可以执行增、删、改、查操作的类型,最常见的自然是集合类型,还有字符串类型,所以对于自定义类型没有想出在哪些场景需要使用到,故暂不给出例子!

关注标哥

联系方式 关注 备注
合作联系群 347363861 接项目、私活
iOS直播音视频技术 256239496(群6满) 实名制且群规严,定期清理
标哥博客iOS交流群 211039962(群7新) 群里很活跃,定期清理
标哥博客iOS交流群 324400294(群1满)|494669518(群2满)|494669518(群3满)250351140(群4满)|552095943(群5满) 群里很活跃,定期清理
微信公众号 iOSDevShares或者iOS开发技术分享 关注公众号阅读好文章
新浪微博 @标哥的技术博客 关注微博动态
GITHUB CoderJackyHuang 文章Demo都在GITHUB
联系标哥 关于标哥 保持活跃在最前线

版权声明:本文为【标哥的技术博客】原创出品,欢迎转载,转载时请注明出处!

iOS开发之Copy/MutableCopy iOS开发之Copy/MutableCopy iOS开发之Copy/MutableCopy

原文  http://www.huangyibiao.com/ios-dev-copy-mutablecopy/
正文到此结束
Loading...