数组深复制浅复制(方便阅读)

2022-09-08  本文已影响0人  ZZ_军哥

一:数组的copy和mutableCopy:

@interface GYJTest : NSObject
@property(nonatomic,copy)NSString *str;
@property(nonatomic,assign)int age;
@end
@implementation GYJTest
@end
- (void)viewDidLoad{
    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]);
}
image

打印结果:

image

结论:

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);

打印效果:

image

从结果标明,通过这种方式可以达到对元素的深复制效果,就是需要注意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  "CCModel.h"
#import <objc/runtime.h>

void encodeWithCoder(NSCoder *coder,id instance){
    unsigned int count =0;
    Ivar *ivars =class_copyIvarList([instance class], &count);
    for(int i = 0; i < count; i++){
        Ivar ivar = ivars[i];
        const char *cKey = ivar_getName(ivar);
        NSString *key = [NSString stringWithCString:cKey encoding:NSUTF8StringEncoding];
        id value = [instance valueForKey:key];
        [coder encodeObject:value forKey:key];
    }
    free(ivars);
}
void createInstanceByCoder(NSCoder *coder,id instance){
    unsigned int count =0;
    Ivar*ivars = class_copyIvarList([instance class], &count);
    for(int i = 0; i < count; i++){
        Ivar ivar = ivars[i];
        const char*cKey = ivar_getName(ivar);
        NSString *key = [NSString stringWithCString:cKey encoding:NSUTF8StringEncoding];
        id value = [coder decodeObjectForKey:key];
        [instance setValue:value forKey: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);

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

image
上一篇 下一篇

猜你喜欢

热点阅读