0x01 场景
现在需要将一个数组中的元素进行排序,然后对对象进行标记,但是又不能影响到原来的数据,那么我们就需要制造一个备份。
要求:这个备份,不仅数组跟原来不同,数组中的内容也不能与原来一样。
准备工作:
@interface Person : NSObject
@property (nonatomic, copy) NSString *name;
@property (nonatomic, assign) NSInteger age;
@end
NSMutableArray *tmpArr = @[].mutableCopy;
for (int i = 0; i<5; i++) {
Person *p = [Person new];
p.name = @(i).stringValue;
p.age = i;
[tmpArr addObject:p];
}
0x01 [array copy]
NSArray *tmp2 = [tmpArr copy];
效果图对比:

与我们设想并不冲突,通过copy
确实生成一个不可变的Array
对象。
但是我们需要时可变的数组,里面的对象还要与原来的对象不是同一个,那尝试下mutableCopy
0x02 [array mutableCopy]
NSMutableArray *tmp2 = [tmpArr mutableCopy];

虽然生成了一个可变数组,但是我们的可变数组中的内容依旧是原来内容,如果修改了依然会导致源数据发生改变。
所以这种方案依然不可选。
0x03 怎样实现数组深拷贝
该怎么实现数组深拷贝呢?查看系统API
方法,可以看到:
// NSArray.h
- (instancetype)initWithArray:(NSArray<ObjectType> *)array copyItems:(BOOL)flag;
如果
flag
为YES
,那么就会去调用array
中对象的copy
方法。
如果flag
为NO
,只是把数组中的对象做一次retain
操作,再赋值给新对象。
通过上面描述可以了解到,如果flag
我们传入YES
,然后重写Person
类的copy
方法,那就可以自己实现深拷贝。
代码如下:
// .h
@interface Person : NSObject <NSCopying>
@property (nonatomic, copy) NSString *name;
@property (nonatomic, assign) NSInteger age;
@end
// .m
- (id)copyWithZone:(nullable NSZone *)zone {
Person *p = [Person new];
p.name = self.name;
p.age = self.age;
return p;
}
// 调用
NSMutableArray *tmp2 = [[NSMutableArray alloc] initWithArray:tmpArr copyItems:YES];

得到结果为,tmp2
是个可变数组,并且里面的对象做了深拷贝。
0x04 总结
copy
/mutableCopy
只能让调用此方法的对象创建一个不可变/可变的对象,但是并能将其影响到里面的内容。
如果需要影响其内容,应该用某种机制,让内部的对象自己调用自己的copy
/mutableCopy
方法。
网友评论