iOS内存管理之copy mutableCopy

2021-11-03  本文已影响0人  夜凉听风雨

不可变类型调用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是一样的。

上一篇下一篇

猜你喜欢

热点阅读