ios&object-c深浅拷贝解析

一.对象的深浅拷贝

对象要实现拷贝就要实现NSCopying或者NSMutableCoping协议,即实现下面两个函数之一
- (id)copyWithZone:(nullable NSZone *)zone
- (id)mutableCopyWithZone:(nullable NSZone *)zone


完整的深拷贝实例:
Student类
Student.h 文件
#import 
#import "Score.h"

@interface Student : NSObject

@property(strong,nonatomic) NSString *mName;
@property(strong,nonatomic) NSString *mAge;
@property(strong,nonatomic) Score *mScore;

-(id)initWithName:(NSString*)name andAge:(NSString*)age andScore:(Score*)score;

@end

Student.m文件
#import "Student.h"

@implementation Student

-(id)initWithName:(NSString*)name andAge:(NSString*)age andScore:(Score*)score{
    self = [super init];
    self.mName = name;
    self.mAge = age;
    self.mScore = score;
    return self;
}

- (id)copyWithZone:(nullable NSZone *)zone
{
    Student *copy = [[[self class] allocWithZone:zone] init];
    copy.mName = self.mName;
    copy.mAge = self.mAge;
    copy.mScore = [self.mScore copy];
    return copy;
}
@end

Score类
Score.h文件
#import 
@interface Score : NSObject
@property(strong,nonatomic) NSString *mChinese;
@property(strong,nonatomic) NSString *mEnglish;
-(id)initWithChi:(NSString*)chi andEng:(NSString*)eng;
@end

Score.m文件
#import "Score.h"

@implementation Score

-(id)initWithChi:(NSString*)chi andEng:(NSString*)eng{
    self = [super init];
    self.mChinese = chi;
    self.mEnglish = eng;
    return self;
}

- (id)copyWithZone:(nullable NSZone *)zone{
    Score *copy = [[[self class] allocWithZone:zone] init];
    copy.mChinese = self.mChinese;
    copy.mEnglish = self.mEnglish;
    return copy;
}

@end


测试函数
Score *score = [[Score alloc] initWithChi:@"88" andEng:@"66"];
Student *stu = [[Student alloc] initWithName:@"fufu" andAge:@"20" andScore:score];
/*
1.没有实现copyWithZone直接报错
2.如果copyWithZone中的copy.mScore = [self.mScore copy]改成copy.mScore = self.mScore ,属于浅拷贝
3.如果Score中没有实现copyWithZone,则在Student的copyWithZone不能copy.mScore = [self.mScore copy],也属于浅拷贝
4.综上,Score中实现copyWithZone,在Student的copyWithZone中调copy.mScore = [self.mScore copy],才属于深拷贝
*/
Student *stuCopy = [stu copy];  
[stu setMName:@"ufuf"];
[stu.mScore setMChinese:@"90"];

二.容器的深浅拷贝(以NSMutableArray为例)

深拷贝
/*
1.用[[NSMutableArray alloc] initWithArray:muArray copyItems:YES];
2.Student对象实现深拷贝
*/
Score *score1 = [[Score alloc] initWithChi:@"11" andEng:@"11"];
Student *stu1 = [[Student alloc] initWithName:@"fufu" andAge:@"10" andScore:score1];
Score *score2 = [[Score alloc] initWithChi:@"22" andEng:@"22"];
Student *stu2 = [[Student alloc] initWithName:@"tutu" andAge:@"20" andScore:score2];
NSMutableArray *muArray = [[NSMutableArray alloc] initWithObjects:stu1,stu2 ,nil];
NSMutableArray *muArrayCopy = [[NSMutableArray alloc] initWithArray:muArray copyItems:YES];    

//以下操作不会影响muArrayCopy
Student *temp = [muArray objectAtIndex:0];
[temp setMName:@"temp"];
[temp.mScore setMChinese:@"12"];

浅拷贝,元素地址都是一样的
[muArray copy];
[muArray mutableCopy];
[NSMutableArray arrayWithArray:muArray];

三.字典的深浅拷贝(以NSMutableDictionary为例),与二类似

深拷贝
Score *score1 = [[Score alloc] initWithChi:@"11" andEng:@"11"];
Student *stu1 = [[Student alloc] initWithName:@"fufu" andAge:@"10" andScore:score1];
NSMutableDictionary *dic = [[NSMutableDictionary alloc] init];
[dic setObject:stu1 forKey:@"key"];
NSMutableDictionary *copyDic = [[NSMutableDictionary alloc]initWithDictionary:dic copyItems:YES];
    
Student *temp = [dic objectForKey:@"key"];
[temp setMName:@"temp"];
[temp.mScore setMChinese:@"12"];


浅拷贝
[dic copy];
[dic mutableCopy];
[NSMutableDictionary dictionaryWithDictionary:dic];

四.copy与mutableCopy的区别

1.对于Array和Dictory,copy出来的是immutable,mutableCopy出来的是mutable
2.对于自定义的对象,根据需求实现逻辑即可。比如类中有NSString,NSdictory,NSArray等变量,copy和mutable可区于这些变量的copy是mutable与否)

NSArray *array = [[NSArray alloc] initWithObjects:@"1",@"2", nil];
NSArray *copyArray = [array copy];
NSMutableArray *mutableCopyArray = [array mutableCopy];
[mutableCopyArray removeObjectAtIndex:0];//正常

NSMutableArray *mutableArray = [[NSMutableArray alloc] initWithObjects:@"1", @"2",nil];
NSMutableArray *copyArray1 = [mutableArray copy];
[copyArray1 removeObjectAtIndex:0];//报错闪退
NSMutableArray *mutableCopyArray1 = [mutableArray mutableCopy];




你可能感兴趣的:(ios)