您的位置:首页 > 运维架构

foundation——NSCopying NSMutableCopying

2017-04-01 17:18 357 查看

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
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息