foundation——NSCopying NSMutableCopying

NSCopying&NSMutableCopying protocol

@protocol NSCopying

- (id)copyWithZone:(nullable NSZone *)zone;

@end

@protocol NSMutableCopying

- (id)mutableCopyWithZone:(nullable NSZone *)zone;

@end

copy&mutableCopy

- (id)copy;
- (id)mutableCopy;
总结:
  • copy和mutableCopy是NSObject方法成员,因此任何继承自NSObject的类都可调用
  • copy调用copyWithZone,mutableCopy调用mutableCopyWithZone
  • NSObject并没有实现NSCopying和NSMutableCopying,因此类如果没有遵守NSCopying和NSMutableCopying,调用copy和mutableCopy会crash

预定义NSCopying&NSMutableCopying区别

- (void)immutable_mutable
{
    NSArray *imArray = [NSArray arrayWithObjects:@"dog", nil];
    id imArray_im = [imArray copy];
    id imArray_m = [imArray mutableCopy];
    
    NSLog(@"imArray addr = %p, imArray RC = %ld, imArray type = %s", imArray, [imArray retainCount], object_getClassName(imArray));
    NSLog(@"imArray_im addr = %p, imArray_im RC = %ld, imArray_im type = %s", imArray_im, [imArray_im retainCount], object_getClassName(imArray_im));
    NSLog(@"imArray_m addr = %p, imArray_m RC = %ld, imArray_m type = %s", imArray_m, [imArray_m retainCount], object_getClassName(imArray_m));
    
    NSMutableArray *mArray = [NSMutableArray arrayWithObjects:@"dog", nil];
    id mArray_im = [mArray copy];
    id mArray_m = [mArray mutableCopy];
    
    NSLog(@"mArray addr = %p, mArray RC = %ld, mArray type = %s", mArray, [mArray retainCount], object_getClassName(mArray));
    NSLog(@"mArray_im addr = %p, mArray_im RC = %ld, mArray_im type = %s", mArray_im, [mArray_im retainCount], object_getClassName(mArray_im));
    NSLog(@"mArray_m addr = %p, mArray_m RC = %ld, mArray_m type = %s", mArray_m, [mArray_m retainCount], object_getClassName(mArray_m));
}
output:
imArray addr = 0x7fd4a3cc3190, imArray RC = 2, imArray type = __NSArrayI
imArray_im addr = 0x7fd4a3cc3190, imArray_im RC = 2, imArray_im type = __NSArrayI
imArray_m addr = 0x7fd4a3cbf8a0, imArray_m RC = 1, imArray_m type = __NSArrayM
mArray addr = 0x7fd4a3cb9050, mArray RC = 1, mArray type = __NSArrayM
mArray_im addr = 0x7fd4a3cc59b0, mArray_im RC = 1, mArray_im type = __NSArrayI
mArray_m addr = 0x7fd4a3cc2720, mArray_m RC = 1, mArray_m type = __NSArrayM
总结:
  • 不管immutable实例对象还是mutable实例对象,copy返回immutable实例对象,mutableCopy返回mutable实例对象
  • immutable实例对象,copy返回的immutable实例对象和original实例对象指向同一实例对象,相当于retain或strong,即引用计数+1

自定义NSCopying&NSMutableCopying

@interface FBAnimal : NSObject <NSCopying, NSMutableCopying>
{
    NSString *_name;
}

- (instancetype)initName:(NSString *)name;

@end

@implementation FBAnimal

- (instancetype)initName:(NSString *)name
{
    self = [super init];
    if(self)
    {
        _name = [NSString stringWithString:name];
    }
    
    return self;
}

- (id)copyWithZone:(NSZone *)zone
{
    NSLog(@"class %s copy", object_getClassName(self));
    
    [self->_name copy];
    [self retain];
    
    return self;
}

- (id)mutableCopyWithZone:(NSZone *)zone
{
    NSLog(@"class %s mutableCopy", object_getClassName(self));
    
    FBAnimal *animal = [[[self class] allocWithZone:zone] init];
    animal->_name = [self->_name copy];
    
    return animal;
}

@end

@interface FBDog : FBAnimal
{
    NSString *_breed;
}

- (instancetype)initBreed:(NSString *)breed;

@end

@implementation FBDog

- (instancetype)initBreed:(NSString *)breed
{
    self = [super initName:@"dog"];
    if(self)
    {
        _breed = [NSString stringWithString:breed];
    }
    
    return self;
}

- (id)copyWithZone:(NSZone *)zone
{
    self = [super copyWithZone:zone];
    [self->_breed copy];
    
    return self;
}

- (id)mutableCopyWithZone:(NSZone *)zone
{
    FBDog *dog = [super mutableCopyWithZone:zone];
    [dog->_breed copy];
    
    return dog;
}

@end
- (void)immutable_mutable
{
    FBAnimal *animal = [[FBAnimal alloc] initName:@"animal"];
    id animal_im = [animal copy];
    id animal_m = [animal mutableCopy];
    
    NSLog(@"animal addr = %p, animal RC = %ld, animal type = %s", animal, [animal retainCount], object_getClassName(animal));
    NSLog(@"animal_im addr = %p, animal_im RC = %ld, animal_im type = %s", animal_im, [animal_im retainCount], object_getClassName(animal_im));
    NSLog(@"animal_m addr = %p, animal_m RC = %ld, animal_m type = %s", animal_m, [animal_m retainCount], object_getClassName(animal_m));
    
    FBDog *dog = [[FBDog alloc] initBreed:@"husky"];
    id dog_im = [dog copy];
    id dog_m = [dog mutableCopy];
    
    NSLog(@"dog addr = %p, dog RC = %ld, dog type = %s", dog, [dog retainCount], object_getClassName(dog));
    NSLog(@"dog_im addr = %p, dog_im RC = %ld, dog_im type = %s", dog_im, [dog_im retainCount], object_getClassName(dog_im));
    NSLog(@"dog_m addr = %p, dog_m RC = %ld, dog_m type = %s", dog_m, [dog_m retainCount], object_getClassName(dog_m));
}
output:
class FBAnimal copy
class FBAnimal mutableCopy
animal addr = 0x7ff1d0d16280, animal RC = 2, animal type = FBAnimal
animal_im addr = 0x7ff1d0d16280, animal_im RC = 2, animal_im type = FBAnimal
animal_m addr = 0x7ff1d0d18000, animal_m RC = 1, animal_m type = FBAnimal
class FBDog copy
class FBDog mutableCopy
dog addr = 0x7ff1d0d19300, dog RC = 2, dog type = FBDog
dog_im addr = 0x7ff1d0d19300, dog_im RC = 2, dog_im type = FBDog
dog_m addr = 0x7ff1d0d1a330, dog_m RC = 1, dog_m type = FBDog

@property的copy修饰词

- (void)property_copy
{
    FBAnimal *animal = [[FBAnimal alloc] initName:@"animal"];
    FBDog *dog = [[FBDog alloc] initBreed:@"husky"];
    
    FBFarm *farm = [[FBFarm alloc] init];
    farm.animal = animal;
    farm.dog = dog;
}
output:
class FBAnimal copy
class FBDog copy
结论:
  • @property的copy修饰符本质就是调用setter时,调用实例对象(setter参数)copy,copy调用copyWithZone,因此property对应类型必须遵守NSCopying
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值