美文网首页
让自己创建的类具备Copy功能

让自己创建的类具备Copy功能

作者: JoliLove | 来源:发表于2018-08-27 21:13 被阅读70次

对于对象具有拷贝功能,则需实现 NSCopying 协议。

  1. 声明该类遵从 NSCopying 协议
@interface Animal : NSObject <NSCopying>

@property (nonatomic, readonly, copy) NSString *name;
@property (nonatomic, readonly, assign) NSInteger age;
@property (nonatomic, assign) NSString *food;

- (instancetype)initWithName:(NSString *)name age:(NSInteger)age food:(NSString *)food;

@end
  1. 实现 NSCopying 协议。该协议只有一个方法: - (id)copyWithZone:(NSZone *)zone;
- (instancetype)initWithName:(NSString *)name age:(NSInteger)age food:(NSString *)food
{
    if (self = [super init]) {
        _name = name;
        _age = age;
        _food = food;
    }
    return self;
}

- (id)copyWithZone:(NSZone *)zone
{
    Animal *copy = [[[self class] allocWithZone:zone] initWithName:_name age:_age food:_food];
    return copy;
}
  1. 但一个类中不仅仅就只有几个基本的属性吧,假如Animal 中含有一个数组,与其他 Animal 对象建立或解除朋友关系的那些方法都需要操作这个数组,那么就需要把包含朋友对象的数组也一并拷贝过来。
@property (nonatomic, strong) NSMutableArray *friends;

- (instancetype)initWithName:(NSString *)name age:(NSInteger)age food:(NSString *)food
{
    if (self = [super init]) {
        _name = name;
        _age = age;
        _food = food;
        _friends = [[NSMutableArray alloc] init];
    }
    return self;
}

- (id)copyWithZone:(NSZone *)zone
{
    Animal *copy = [[[self class] allocWithZone:zone] initWithName:_name age:_age food:_food];
    
    copy.friends = [_friends mutableCopy];
    
    return copy;
}

- (void)addFriend:(Animal *)animal
{
    [_friends addObject:animal];
}

- (void)removeFriend:(Animal *)animal
{
    [_friends removeObject:animal];
}
  1. 写代码验证下:
Animal *dog = [[Animal alloc] initWithName:@"哈士奇" age:3 food:@"骨头"];

NSLog(@"dog 地址 %p", dog);
NSLog(@"dog.name %@ -- 地址 %p",dog.name, dog.name);
    
Animal *dog11 = [dog copy];
NSLog(@"dog11 地址 %p", dog11);
NSLog(@"dog11.name %@ -- 地址 %p",dog11.name, dog11.name);

运行结果

2018-08-27 16:48:28 [2384:424494] dog 地址 0x6000002413b0
2018-08-27 16:48:28 [2384:424494] dog.name 哈士奇 -- 地址 0x10319d0b0
2018-08-27 16:48:31 [2384:424494] dog11 地址 0x600000241680
2018-08-27 16:48:31 [2384:424494] dog11.name 哈士奇 -- 地址 0x10319d0b0

(lldb) po dog.friends
<__NSArrayM 0x60400025b4e0>(
<Animal: 0x60400025b600>,
<Animal: 0x60400025b5a0>
)

(lldb) po dog11.friends
<__NSArrayM 0x60000024b5e0>(
<Animal: 0x60400025b600>,
<Animal: 0x60400025b5a0>
)

可以看到,dog和dog11的地址是不同的,成功copy。数组friends中的元素也被copy了。 但还是有缺陷, 因为打印的结果 name和friends中元素的值一样但是地址不一样。可以得出 copy是浅拷贝 只是拷贝了 指针,并没有对内容进行拷贝。如果不要求内容拷贝, 以上便能满足对象copy功能的基本需求。

  1. 存放朋友对象的 friends 是用 “copyWithZone:” 方法来拷贝的,这种浅拷贝方式不会逐个复制 friends 中的元素。若需要深拷贝的话,则需要编写一个专供深拷贝所用的方法。
- (id)deepCopy
{
    Animal *copy = [[[self class] alloc] initWithName:_name age:_age food:_food];
    
    copy.friends = [[NSMutableArray alloc] initWithArray:_friends copyItems:YES];
    
    return copy;
}

继续代码验证:

Animal *dog12 = [dog deepCopy];
NSLog(@"dog12 地址 %p", dog12);
NSLog(@"dog12.name %@ -- 地址 %p", dog12.name);

运行结果:

2018-08-27 20:59:22 [4423:610720] dog12 地址 0x60400025b450
2018-08-27 20:59:22 ObjectCopy[1888:367803] dog12.name 地址 0x10831e380

(lldb) po dog12.friends
<__NSArrayM 0x60000024b8b0>(
<Animal: 0x60400025b750>,
<Animal: 0x60000024ba00>
)

可以看出对象dog12的name地址和dog的name地址不一样, friends中的元素也被一一复制了,这样对象copy功能就完成了。

相关文章

网友评论

      本文标题:让自己创建的类具备Copy功能

      本文链接:https://www.haomeiwen.com/subject/ehzziftx.html