先来看一段代码
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<NSCoding, NSCopying>
@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<NSCopying>
@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
类型,为什么会报不存在方法的错误呢?因为在合成getter
和setter
方法的时候没有提供mutableCopy
指示符,因此即使定义实例变量时使用了可变类型
,但只要使用copy
指示符,实例变量实际得到的值总是不可变对象
,系统默认的setter
方法如下
- (void)setName:(NSMutableString *)name
{
_name = [name copy];
}
因此需要在person.m
文件中添加如下代码
- (void)setName:(NSMutableString *)name
{
_name = [name mutableCopy];
}
p2.book
任意属性变化也会影响到p1.book
的属性
这里需要修改两个地方
- 让
Book
类实现NSCopying
协议 - 在
Person.m
的- (id)copyWithZone:(NSZone *)zone
方法中将copy.book = self.book;
替换成copy.book = [self.book copy];