深copy和浅copy

NSCopying与NSMutableCopy协议

怎么让我们自己定义的类可以调用copy或mutableCopy来复制一个对象的副本呢?

  • 1 定义一个User对象
@interface User : NSObject
@property (nonatomic ,strong) NSMutableString *name;
@property (nonatomic ,assign) int age;
@end
- (void)viewDidLoad {
    [super viewDidLoad];

    User *user1 = [[User alloc] init];
    user1.name = @"张三";
    user1.age = 20;

    User *user2 = [user1 copy];
//    User *user2 = [user1 mutableCopy];

    NSLog(@"%@",user2.name);

}

运行
这里写图片描述
错误提示找不到 copyWithZone方法,打开注释部分代码User *user2 = [user1 mutableCopy];再次运行
这里写图片描述 错误提示找不到 mutableCopyWithZone方法

由上面的举例我们可以看出要想一个类可以copy一个不变类我们需要做

  • 1 遵循NSCopying协议
  • 2 重写copyWithZone方法

使用mutableCopy复制一个可变的副本需要

  • 1 遵循NSMutableCopy协议
  • 2 重写mutableCopyWithZone方法

    当我们调用对象的copy方法时,实质上是底层调用copyWithZone方法返回一个不可变的副本,当我们调用mutableCopy方法时,会调用mutableCopyWithZone方法返回一个可变的副本,从上面的示例可以看出如果希望我们自己的类来调用copy或mutableCopy方法必需实现copyWithZone或mutableCopyWithZone方法

为了我们自己的类可以调用copy方法我们实现copyWithZone方法


#import "User.h"

@implementation User
- (id)copyWithZone:(NSZone *)zone {
    User *user = [[[self class] allocWithZone:zone] init];
    user.name = self.name;
    user.age = self.age;
    return user;

}
@end
- (void)viewDidLoad {
    [super viewDidLoad];

    User *user1 = [[User alloc] init];
    user1.name = [NSMutableString stringWithFormat:@"张三" ];
    user1.age = 20;

    User *user2 = [user1 copy];
    user2.name = [NSMutableString stringWithFormat:@"李四" ];;

    NSLog(@"user1%@",user1.name);
    NSLog(@"user2%@",user2.name);
    // Do any additional setup after loading the view, typically from a nib.
}

运行打印结果
这里写图片描述 没有问题

如果把user2.name = [NSMutableString stringWithFormat:@"李四" ]换成[user2.name replaceCharactersInRange:NSMakeRange(0, 2) withString:@"李四"];运行结果会是怎样的呢?
运行一下结果如下图
这里写图片描述
问题来了,我们只是改变了user2的name为什么user1的name也跟着改变了呢?
回过头来我们看一下copyWithZone的实现User *user = [[[self class] allocWithZone:zone] init];
user.name = self.name;
user.age = self.age;
return user;

user对象name指针指向了self.name指针指向的内容,他们实质上指向内存中同一块地址,所以当我们改变user1,user2任意对象的name时两个对象的name都会改变,这种方式的copy就是浅copy,浅copy是指当对象的实例变量是指针变量时,如果只是复制该指针的地址,而不是复制指针指向的对象

从上面的示例来看,浅复制,在内存中复制了两个对象但这两个变量的指针变量指向同一个对象,也就是说这两个对象依然有公共的部分

深复制

- (id)copyWithZone:(NSZone *)zone {
    User *user = [[[self class] allocWithZone:zone] init];
    user.name = [self.name mutableCopy];
    user.age = self.age ;
    return user;

}

user对象name属性是通过[self.name mutableCopy]方法赋值的mutableCopy是复制一个可变对象然后赋值给user.name,保证了user.name和self.name在内存中指向不同的区域,这样user1和user之间在内存中没有共同的区域,这样就实现了深复制
实现深复制之后再次编译代码运行结果如下
这里写图片描述

总结
当对象的实例变量是指针变量时,如果只是复制了该对象实例变量的指针地址,而不是复制指针指向的内容时,这种方式的复制被称为浅copy,深copy不仅会复制对象本身,而且会复制指针类型的实例变量,Foundation框架中的大部分类都只实现了浅复制

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值