美文网首页
model、array多层嵌套的深copy

model、array多层嵌套的深copy

作者: 114105lijia | 来源:发表于2020-02-06 16:00 被阅读0次

    之前碰到一个需求,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];
    

    demo

    相关文章

      网友评论

          本文标题:model、array多层嵌套的深copy

          本文链接:https://www.haomeiwen.com/subject/fmkuxhtx.html