之前碰到一个需求,model和array多层嵌套,需要深copy。如下图结构:
image.png
看到需求后,第一反应就是
NSMutableArray *copyArray = [self.dataArray mutableCopy];
当我查看地址时,发现地址相同:(都是第一个元素的地址)
image.png
然后我想到的是,在model里面实现copy、mutablecopy协议,之后查看数组地址,还是相同。
当我mutablecopy数组里面的model时,2个model的地址确实不同,但是model里面的数组的地址又相同了。如下图:
image.png
之后想的是用归档和反归档:
- (void)archiverCopy {
NSString *filePath = [NSHomeDirectory() stringByAppendingString:@"person.plist"];
//归档 ios (2.0,12.0)
BOOL success = [NSKeyedArchiver archiveRootObject:self.dataArray toFile:filePath];
NSLog(@"%d",success);
// 反归档
NSMutableArray *copyArray = [NSKeyedUnarchiver unarchiveObjectWithFile:filePath];
NSLog(@"%@",copyArray);
}
最后查看地址,确实能实现model和array里面的每个元素都深copy,不过archiveRootObject方法只到iOS 12.0,之后需要使用archivedDataWithRootObject,即下面的方法:
- (void)archiverToCopy {
//归档
NSString *path = NSHomeDirectory();
path = [path stringByAppendingString:@"Singel.plist"];
//2:准备存储数据对象(用可变数组进行接收)
NSMutableData *data = [NSMutableData new];
//3:创建归档对象
NSKeyedArchiver *archiver = [[NSKeyedArchiver alloc]initForWritingWithMutableData:data];
//4:开始归档
[archiver encodeObject:self.dataArray forKey:@"cate"];
//5:完成归档
[archiver finishEncoding];
//6:写入文件
BOOL result = [data writeToFile:path atomically:YES];
if (result) {
NSLog(@"归档成功:%@",path);
}
//反归档
//1:获取解档路径
NSData *MyData = [NSData dataWithContentsOfFile:path];
//2:创建反归档对象
NSKeyedUnarchiver *unarchiver= [[NSKeyedUnarchiver alloc]initForReadingWithData:MyData];
//3:反归档
// BigCateMode *bigModel = [BigCateMode new];
NSMutableArray *archiverDataArray = [NSMutableArray array];
archiverDataArray = [unarchiver decodeObjectForKey:@"cate"];
//4:结束归档
[unarchiver finishDecoding];
}
注意:使用归档和反归档时,model里面要实现encodeWithCoder和initWithCoder方法,不然会闪退。如下:
-(void)encodeWithCoder:(NSCoder *)aCoder{
//对实例变量 进行归档
[aCoder encodeObject:_bigCateName forKey:@"bigCateName"];
[aCoder encodeObject:_bigCateCode forKey:@"bigCateCode"];
[aCoder encodeObject:_bigCatelist forKey:@"bigCatelist"];
}
-(id)initWithCoder:(NSCoder *)aDecoder{
if ([super init]) {
self.bigCateName =[aDecoder decodeObjectForKey:@"bigCateName"];
self.bigCateCode = [aDecoder decodeObjectForKey:@"bigCateCode"];
self.bigCatelist = [aDecoder decodeObjectForKey:@"bigCatelist"];
}
return self;
}
使用归档和反归档,虽然可以实现深copy,但实现时,里面的每个model都需要实现归档和反归档方法,总感觉太麻烦。
其实要达到深copy的目的,就是把数组里面的每个元素,包括元素里面的对象或数组重新生成一个,自己一个一个的写,肯定嫌麻烦,不过利用runtime却可以一劳永逸。
我也偷个懒,直接用第三方框架MJExtension里面的方法,先将model转化为dictionary,然后转化成model。达到深copy的目的。如下:
//mjextension 实现深copy 注意要在.m文件中实现数组和model的映射
NSDictionary *dic = [bigModel mj_keyValues];
BigCateMode *mjCopyModel = [BigCateMode mj_objectWithKeyValues:dic];
网友评论