心得:
不管是copy
还是mutableCopy
,目的都是拷贝出来一个新的对象,并且值都不变。
由于值不变所以:
- 只讨论是否需要为这个新对象分配内存。
- 从被拷贝的对象是
可变
还是不可变
开始讨论: - 该对象是否支持
copy
和mutableCopy
不可变对象:
copy
出来的是不可变对象(由于都是不可变的,所以不需要再次分配内存)浅拷贝
mutableCopy
出来的是可变对象(需要为新对象再次分配内存)深拷贝
可变对象:
copy
出来的也是不可变对象(需要分配内存,因为在修改可变对象的时候要保证copy
出来的对象不受影响)深拷贝
mutableCopy
出来的是可变对象(需要分配内存,因为两个对象之间修改需要互不干扰)深拷贝
实际使用中的第一种情况:
@interface YSPerson : NSObject
@property (nonatomic, copy) NSArray *arr;
@property (nonatomic, copy) NSMutableArray *arrM;
@end
@implementation YSPerson
- (void)setArr:(NSArray *)arr {
if (_arr != arr) {
_arr = [arr copy];
}
}
- (void)setArrM:(NSMutableArray *)arrM {
if (_arrM != arrM) {
_arrM = [arrM copy];
}
}
@end
- 使用
copy
修饰的属性实际上自动生成了这样的代码,由于NSArray
本来就是不可变对象,copy之后的副本指向和原对象相同,所以没什么影响;但是NSMutableArray
使用copy之后,生成的副本是一个不可变对象(即NSArray
),且重新分配了一块内存给副本。此时如果外部调用
YSPerson *person = [YSPerson new];
person.arrM = [NSMutableArray array];
[person.arrM addObject:@"x1"];
程序就会崩溃,因为person.arrM实际变成了NSArray
对象,NSArray
是没有addObject:
方法的。
实际使用中的第二种情况:
有时候会有copy自定义类对象的需求,但如果直接使用copy会报找不到copyWithZone:
方法,解决办法:实现<NSCopying>
协议下的copyWithZone:
方法,如下:
@interface YSPerson : NSObject<NSCopying>
@property (nonatomic, copy) NSString *name;
@property (nonatomic, copy) NSString *address;
@end
@implementation YSPerson
- (id)copyWithZone:(NSZone *)zone {
YSPerson *p = [[YSPerson allocWithZone:zone] init];// zone为内存区域
// 选择需要copy的属性
p.name = self.name;
p.address = self.address;
return p;
}
@end
这样就可以在外部直接对YSPerson
对象进行copy操作了
YSPerson *p1 = [YSPerson new];
p1.name = @"xx";
p1.address = @"中国";
YSPerson *p2 = [p1 copy];
NSLog(@"name:%@, address:%@", p2.name, p2.address);
// 打印结果:name:xx, address:中国
网友评论