iOS内存管理之copy mutableCopy
不可变类型调用copy方法是不可变类型。
可变类型调用copy方法会复制出不可变类型。
不可变类型调用mutableCopy方法会复制出可变类型。
可变类型调用mutableCopy方法会复制出可变类型。
不可变类型调用copy方法不会拷贝出一个副本,只会增加引用计数,指向的还是之前的地址,所以称之为浅拷贝。
浅拷贝.png不可变类型和可变类型调用mutableCopy方法或者可变类型调用copy方法都会拷贝出一个副本,指向的地址和之前的地址完全不同,所以称之为深拷贝。
可变类型深拷贝.png 可变类型深拷贝.png 不可变类型深拷贝.png说到copy操作 ,不得不说NSCopying和NSMutableCopying协议。
如果类想要支持copy操作,则必须实现NSCopying协议,也就是说实现copyWithZone方法;
如果类想要支持mutableCopy操作,则必须实现NSMutableCopying协议,也就是说实现mutableCopyWithZone方法;
iOS系统中的一些类已经实现了NSCopying或者NSMutableCopying协议的方法,如果向未实现相应方法的系统类或者自定义类发送copy或者mutableCopy消息,则会crash。
自定义的类型
现在创建一个Person类继承自NSObject,如果对Person类对象调用copy方法,我们需要在Person类里遵守NSCopying协议,并实现- (id)copyWithZone:(NSZone *)zone
协议方法。
- (id)copyWithZone:(NSZone *)zone{
Person *model = [[[self class] allocWithZone:zone] init];
model.name = self.name;
model.age = self.age;
// 未公开的成员
model->_nickName = _nickName;
// 可变的成员
model.cars = [self.cars mutableCopyWithZone:zone];
return model;
}
说明:在- (id)copyWithZone:(NSZone *)zone
方法中,一定要通过[self class]
方法返回的对象调用allocWithZone:
方法。因为指针可能实际指向的是Person
的子类。这种情况下,通过调用[self class]
,就可以返回正确的类的类型对象。
Person *p1 = [[Person alloc] init];
p1.name = @"Jonas";
p1.age = 28;
p1.cars = [NSMutableArray alloc] init];
[p1.cars addObject:@"奔驰"];
[p1.cars addObject:@"宝马"];
Person *p2 = [p1 copy];
NSLog(@"p1===%p, p2===%p", p1, p2);
NSLog(@"name==%@, age==%ld", p2.name, p2.age);
打印结果:
p1===0x600003530f20, p2===0x600003530fe0
name==Jonas, age==28
可以看到p1和p2地址是不同的,但是name和age是一样的。