NSCopying协议

先来看一段代码

NSMutableArray *arr1 = [[NSMutableArray alloc] initWithObjects:@1, @2, @3, nil];
NSMutableArray *arr2 = arr1;
[arr1 removeObjectAtIndex:0];

在删除arr1第一个元素的同时,arr2的第一个元素也被删除了,这很好理解,因为两个对象都指向同一个地址
如果想操作arr1的同时不影响到arr2,则只需改动一句

NSMutableArray *arr2 = [arr1 copy];

如果调用copy方法的对象是自己定义的对象,那么该对象需要实现NSCopying协议
Person.h

@interface Person : NSObject

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

@end

Person.m

- (id)copyWithZone:(NSZone *)zone
{
    Person *copy = [[[self class] alloc] init];
    
    copy.name = self.name;
    copy.age  = self.age;
    
    return copy;
}

更复杂的情况

@interface Book : NSObject
@property(nonatomic, copy) NSString *name;
@property(nonatomic, assign) float price;
@end
@interface Person : NSObject
@property(nonatomic, copy) NSMutableString *name;
@property(nonatomic, strong) Book *book;
@end

@implementation Person
- (id)copyWithZone:(NSZone *)zone
{
    Person *copy = [[[self class] alloc] init];
    copy.name = self.name;
    copy.book = self.book;
    return copy;
}

调用

Book *book = [Book new];
book.name = @"OBJC";
book.price = 89.99;

Person *p1 = [Person new];
p1.name = [NSMutableString stringWithString:@"JC"];
p1.book = book;

Person *p2 = [p1 copy];

[p2.name appendString:@"Henry"];//这里会报错(unrecognized selector)
p2.book.name = @"JAVA";
p2.book.price = 79.99;

这里需要重点注意下,程序中p2.name明明定义的是NSMutableString类型,为什么会报不存在方法的错误呢?因为在合成gettersetter方法的时候没有提供mutableCopy指示符,因此即使定义实例变量时使用了可变类型,但只要使用copy指示符,实例变量实际得到的值总是不可变对象,系统默认的setter方法如下

- (void)setName:(NSMutableString *)name
{
    _name = [name copy];
}

因此需要在person.m文件中添加如下代码

- (void)setName:(NSMutableString *)name
{
    _name = [name mutableCopy];
}

p2.book任意属性变化也会影响到p1.book的属性
这里需要修改两个地方

  1. Book类实现NSCopying协议
  2. Person.m- (id)copyWithZone:(NSZone *)zone方法中将copy.book = self.book;替换成copy.book = [self.book copy];

你可能感兴趣的:(NSCopying协议)