细说@property(五)

copy和mutableCopy

copy和mutableCopy之间的差异主要和深拷贝和浅拷贝有关,先看一下深拷贝、浅拷贝的概念。

深拷贝、浅拷贝
所谓浅拷贝,在Objective-C中可以理解为引用计数加1,并没有申请新的内存区域,只是另外一个指针指向了该区域。深拷贝正好相反,深拷贝会申请新的内存区域,原内存区域的引用计数不变。看图来说明深拷贝和浅拷贝的区别。

首先A指向一块内存区域,现在设置B = A



现在B和A指向了同一块内存区域,即为浅拷贝。

我们再来看看深考贝



首先A指向一块内存区域,现在设置B = A
A和B指向的不是同一块内存区域,只是这两块内存区域中的内容是一样的,即为深拷贝。

可变对象的copy、mutableCopy

- (void)testMutableCopy
{
    NSMutableString *str1 = [NSMutableString stringWithString:@"abc"];
    NSString *str2 = [str1 copy];
    NSMutableString *str3 = [str1 mutableCopy];
    NSLog(@"str1 = %p str2 = %p str3 = %p",str1,str2,str3);

    NSMutableArray *array1 = [NSMutableArray arrayWithObjects:@"a",@"b", nil];
    NSArray *array2 = [array1 copy];
    NSMutableArray *array3 = [array1 mutableCopy];
    NSLog(@"array1 = %p array2 = %p array3 = %p",array1,array2,array3);
}

可变对象的copy和mutableCopy都是深拷贝,那么输出结果就是:

2019-02-01 13:01:27.525064+0800 TestClock[9357:143436] str1 = 0x60000086d8f0 str2 = 0xc8c1a5736a50d5fe str3 = 0x60000086d9b0
2019-02-01 13:01:27.525064+0800 TestClock[9357:143436] array1 = 0x600000868000 array2 = 0x60000067e5a0 array3 = 0x600000868030

我们可以看到,只要是可变对象,无论是集合对象,还是非集合对象,copy和mutableCopy都是深拷贝。

不可变对象的copy、mutableCopy

- (void)testCopy
{
    NSString *str1 = @"123";
    NSString *str2 = [str1 copy];
    NSMutableString *str3 = [str1 mutableCopy];
    NSLog(@"str1 = %p str2 = %p str3 = %p",str1,str2,str3);

    NSArray *array1 = @[@"1",@"2"];
    NSArray *array2 = [array1 copy];
    NSMutableArray *array3 = [array1 mutableCopy];
    NSLog(@"array1 = %p array2 = %p array3 = %p",array1,array2,array3);
}

不可变对象的copy是浅拷贝,mutableCopy是深拷贝,那么输出结果就是:

2019-02-01 13:01:27.525064+0800 TestClock[9442:147133] str1 = 0x1045612b0 str2 = 0x1045612b0 str3 = 0x6000017e4450
2019-02-01 13:01:27.525064+0800 TestClock[9442:147133] array1 = 0x6000019f5c80 array2 = 0x6000019f5c80 array3 = 0x6000017e1170

可以看到,只要是不可变对象,无论是集合对象,还是非集合对象,copy都是浅拷贝,mutableCopy都是深拷贝。

自定义对象如何支持copy方法

项目开发中经常会有自定义对象的需求,那么自定义对象是否可以copy呢?如何支持copy?
自定义对象可以支持copy方法,我们所需要做的是:自定义对象遵守NSCopying协议,且实现copyWithZone方法。NSCopying协议是系统提供的,直接使用即可。

  • 遵守NSCopying协议:
@interface Student : NSObject <NSCopying>
{
    NSString *_sex;
}

@property (atomic, copy) NSString *name;

@property (nonatomic, copy) NSString *sex;

@property (nonatomic, assign) int age;

@end
  • 实现CopyWithZone方法:
- (instancetype)initWithName:(NSString *)name age:(int)age sex:(NSString *)sex
{
    if(self = [super init]){
        self.name = name;
        _sex = sex;
        self.age = age;
    }
    return self;
}

- (instancetype)copyWithZone:(NSZone *)zone
{
    // 注意,copy的是自己,因此使用自己的属性
    Student *stu = [[Student allocWithZone:zone] initWithName:self.name age:self.age sex:_sex];
    return stu;
}
  • 测试:
- (void)testStudent
{
    Student *stu1 = [[Student alloc] initWithName:@"Wang" age:18 sex:@"male"];
    Student *stu2 = [stu1 copy];
    NSLog(@"stu1 = %p stu2 = %p",stu1,stu2);
}
  • 结果:
stu1 = 0x600003a41e60 stu2 = 0x600003a41fc0

这里是一个深拷贝,根据copyWithZone方法的实现,应该很容易明白为何是深拷贝。
除了NSCopying协议和copyWithZone方法,对应的还有NSMutableCopying协议和mutableCopyWithZone方法,实现都是类似的,不做过多介绍。

©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

相关阅读更多精彩内容

  • Swift1> Swift和OC的区别1.1> Swift没有地址/指针的概念1.2> 泛型1.3> 类型严谨 对...
    cosWriter阅读 11,809评论 1 32
  • 本文为转载: 作者:zyydeveloper 链接:http://www.jianshu.com/p/5f776a...
    Buddha_like阅读 1,067评论 0 2
  • 前言 不敢说覆盖OC中所有copy的知识点,但最起码是目前最全的最新的一篇关于 copy的技术文档了。后续发现有新...
    zyydeveloper阅读 3,791评论 4 35
  • 🍒今日的学习文章:彻底改变坏习惯,拥有自律又充实的人生 相关图书: 如果要评选世界上对人影响最大的力量,那一...
    TaoMin阅读 349评论 0 0
  • 书名:《今天运气怎么这么好》 (南海出版社2007年版图书) 一本颠覆传统“坏野狼”形象的有趣绘本 内容简介 一本...
    8f95326955fd阅读 547评论 0 1

友情链接更多精彩内容