关于数组的深复制浅复制

一:数组的copy和mutableCopy:

```

@interface GYJTest : NSObject

@property(nonatomic,copy)NSString *str;

@property(nonatomic,assign)int age;

@end

@implementation GYJTest

@end

    GYJTest *test = [[GYJTest alloc]init];

    test.str = [NSString stringWithFormat:@"%ld",1837891291834223121];

    test.age=10;

    NSArray*arr2 =@[test];

    NSArray*arr3 = arr2.copy;

    NSArray*arr4 = arr2.mutableCopy;

    NSLog(@"%p",test);

    NSLog(@"%p",arr2);

    NSLog(@"%p",arr3);

    NSLog(@"%p",arr4);

    NSLog(@"%p",arr3[0]);

    NSLog(@"%p",arr4[0]);

```



打印结果:


结论:

1.单纯的数组copy,只是指针复制,对其中一个数组进行修改,另一个也会跟着变动

2.数组的mutableCopy,属于深复制,会开辟数组的堆空间,但是仅限容器的复制,而容器内存储的指针数值保持不动,如果对元素的内容进行修改,两个数组内容都会跟着变动

二:那么如果要保证数组内容的完整的复制,包括数组元素的深复制,有两种方式

A.调用[[NSMutableArray alloc]initWithArray:arr copyItems:YES]函数进行复制,该函数会继续调用元素的NSCopying协议的- (id)copyWithZone:(nullable NSZone *)zone方法,人为的修改元素的复制内容,以达到深复制的目的,元素CCModel的copying协议按NSMutableCopying方式写,然后CCModel的嵌套层按正常的NSMutableCopying写,如下:

```

@interface CCModel : NSObject<NSCopying>

@property(nonatomic,assign)int count;

@property(nonatomic,strong)Person *per;

@end

@interface Person : NSObject<NSMutableCopying>

@property(nonatomic,copy)NSString *name;

@property(nonatomic,strong)Student *stu;

@end

@interface Student : NSObject<NSMutableCopying>

@property(nonatomic,assign)int score;

@property(nonatomic,copy)NSString *numString;

@end

@implementation CCModel

- (id)copyWithZone:(nullable NSZone *)zone{

    CCModel *model = [[CCModel alloc]init];

    model.count=self.count;

    model.per = self.per.mutableCopy;

    return  model;

}

@end

@implementation Person

- (id)mutableCopyWithZone:(nullable NSZone *)zone{

    Person *model = [[Person alloc]init];

    model.name = self.name.mutableCopy;

    model.stu = self.stu.mutableCopy;

    return  model;

}

@end

@implementation Student

- (id)mutableCopyWithZone:(nullable NSZone *)zone{

    Student *model = [[Student alloc]init];

    model.score=self.score;

    model.numString = self.numString.mutableCopy;

    return  model;

}

@end

```

验证代码:

```

Student *stu = [[Student alloc]init];

    stu.score=90;

    stu.numString = @"2030221134";

    Person *per = [[Person alloc]init];

    per.name=@"tom";

    per.stu= stu;

    CCModel *model = [[CCModel alloc]init];

    model.per= per;

    model.count=1;

    NSArray*arr =@[model];

    NSMutableArray *arr1 = [[NSMutableArray alloc]initWithArray:arr copyItems:YES];

    NSLog(@"ccmodel:%p",model);

    NSLog(@"ccmodel.per:%p",model.per);

    NSLog(@"ccmodel.per.stu:%p",model.per.stu);

    CCModel*copyModel = arr1.firstObject;

    NSLog(@"copyModel:%p",copyModel);

    NSLog(@"copyModel.per:%p",copyModel.per);

    NSLog(@"copyModel.per.stu:%p",copyModel.per.stu);

```

打印效果:


从结果标明,通过这种方式可以达到对元素的深复制效果,就是需要注意CCModel对象以后可别调用model.copy,那可是完全的深复制,完全是两个对象了.

B.第二种方式,序列化操作通过实现NSCoding协议,调用序列化方法,深复制一个内容出来

```

NSArray*arr =@[model];

NSData *data = [NSKeyedArchiver archivedDataWithRootObject:arr];

NSArray *deepCopyArr = [NSKeyedUnarchiver unarchiveObjectWithData:data];

```

写法:

```

@interface CCModel : NSObject<NSCoding>

@property(nonatomic,assign)int count;

@property(nonatomic,strong)Person *per;

@end

@interface Person : NSObject<NSCoding>

@property(nonatomic,copy)NSString *name;

@property(nonatomic,strong)Student *stu;

@end

@interface Student : NSObject<NSCoding>

@property(nonatomic,assign)int score;

@property(nonatomic,copy)NSString *numString;

@end

```

```

#import

void encodeWithCoder(NSCoder *coder,id instance){

    unsignedintcount =0;

    Ivar*ivars =class_copyIvarList([instanceclass], &count);

    for(inti =0; i

        Ivarivar = ivars[i];

        constchar*cKey =ivar_getName(ivar);

        NSString *key = [NSString stringWithCString:cKey encoding:NSUTF8StringEncoding];

        idvalue = [instancevalueForKey:key];

        [coderencodeObject:valueforKey:key];

    }

    free(ivars);

}

void createInstanceByCoder(NSCoder *coder,id instance){

    unsignedintcount =0;

    Ivar*ivars =class_copyIvarList([instanceclass], &count);

    for(inti =0; i

        Ivarivar = ivars[i];

        constchar*cKey =ivar_getName(ivar);

        NSString *key = [NSString stringWithCString:cKey encoding:NSUTF8StringEncoding];

        idvalue = [coderdecodeObjectForKey:key];

        [instancesetValue:valueforKey:key];

    }

    free(ivars);

}

@implementation CCModel

- (void)encodeWithCoder:(NSCoder *)coder{

    encodeWithCoder(coder,self);

}

- (instancetype)initWithCoder:(NSCoder *)coder{

    if (self = [super init]){

        createInstanceByCoder(coder,self);

    }

    return self;

}

@end

@implementation Person

- (void)encodeWithCoder:(NSCoder *)coder{

    encodeWithCoder(coder,self);

}

- (instancetype)initWithCoder:(NSCoder *)coder{

    if (self = [super init]){

        createInstanceByCoder(coder,self);

    }

    return self;

}

@end

@implementation Student

- (void)encodeWithCoder:(NSCoder *)coder{

    encodeWithCoder(coder,self);

}

- (instancetype)initWithCoder:(NSCoder *)coder{

    if (self = [super init]){

        createInstanceByCoder(coder,self);

    }

    return self;

}

@end

```

验证效果

```

   Student *stu = [[Student alloc]init];

    stu.score=90;

    stu.numString = @"2030221134";

    Person *per = [[Person alloc]init];

    per.name=@"tom";

    per.stu= stu;

    CCModel *model = [[CCModel alloc]init];

    model.per= per;

    model.count=1;

    NSArray*arr =@[model];

    NSData *data = [NSKeyedArchiver archivedDataWithRootObject:arr];

    NSArray *deepCopyArr = [NSKeyedUnarchiver unarchiveObjectWithData:data];

    NSLog(@"ccmodel:%p",model);

    NSLog(@"ccmodel.per:%p",model.per);

    NSLog(@"ccmodel.per.stu:%p",model.per.stu);

    CCModel*copyModel = deepCopyArr.firstObject;

    NSLog(@"copyModel:%p",copyModel);

    NSLog(@"copyModel.per:%p",copyModel.per);

    NSLog(@"copyModel.per.stu:%p",copyModel.per.stu);

```

打印结果显示:数组元素及元素嵌套的内容都不是同一个对象,达到了深复制的目的


最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容

  • 设计模式是什么? 你知道哪些设计模式,并简要叙述? 设计模式是一种编码经验,就是用比较成熟的逻辑去处理某一种类型的...
    卑微的戏子阅读 641评论 0 1
  • 1.设计模式是什么? 你知道哪些设计模式,并简要叙述?设计模式是一种编码经验,就是用比较成熟的逻辑去处理某一种类型...
    龍飝阅读 2,244评论 0 12
  • IOS开发之深拷贝与浅拷贝(mutableCopy与Copy)详解 copy与retain的区别: copy是创建...
    第六梦阅读 482评论 0 1
  • 设计模式是什么? 你知道哪些设计模式,并简要叙述? 设计模式是一种编码经验,就是用比较成熟的逻辑去处理某一种类型的...
    iOS菜鸟大大阅读 763评论 0 1
  • 1.设计模式是什么? 你知道哪些设计模式,并简要叙述? 设计模式是一种编码经验,就是用比较成熟的逻辑去处理某一种类...
    司马DE晴空阅读 1,357评论 0 7