一:数组的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]);
}
打印结果:
结论:
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 "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);
打印结果显示:数组元素及元素嵌套的内容都不是同一个对象,达到了深复制的目的