概述
实现拷贝,需要遵守以下两个协议
拷贝返回对象的种类
拷贝的种类
注意
copy
retain
非容器对象(如NSString
))
对于不可变对象
规则
示例
- (void)imutableInstanceCopy
{
NSString *string = @"Welcome to Xcode";
//copy,浅拷贝
NSString *stringCopy = [string copy];
//mutableCopy,返回的对象可变
NSMutableString *stringMutableCopy = [string mutableCopy];
[stringMutableCopy appendString:@"!"];
//string与stringCopy的内存地址相同
NSLog(@"string: %p", string);
NSLog(@"strongCopy: %p", stringCopy);
//string与stringMutableCopy的内存地址不同,分配了新的内存
NSLog(@"stringMCopy:%p", stringMutableCopy);
}
对于可变对象
规则
示例
- (void)mutableInstanceCopy
{
NSMutableString *mutableString = [NSMutableString stringWithString: @"Welcome to Xcode"];
//深拷贝,返回对象不可变
NSString *stringCopy = [mutableString copy];
NSMutableString *mutableStringCopy = [mutableString copy];
//运行时,此句会报错,错误信息“Attempt to mutate immutable object with appendString:”
[mutableStringCopy appendString:@"~~~"];
//深拷贝,返回对象可变
NSMutableString *stringMutableCopy = [mutableString mutableCopy];
[stringMutableCopy appendString:@"!"];
//三者与mutableString的内存地址都不同
NSLog(@"mutableString: %p", mutableString);
NSLog(@"string: %p", stringCopy);
NSLog(@"mutableStringCopy: %p", mutableStringCopy);
NSLog(@"stringMutbleCopy:%p", stringMutableCopy);
}
容器对象(NSArray
)
注意
示例
- (void)containerInstanceShallowCopy
{
NSArray *array = [NSArray arrayWithObjects:[NSMutableString stringWithString:@"Welcome"],@"to",@"Xcode",nil];
//浅拷贝
NSArray *arrayCopy = [array copy];
//深拷贝
NSMutableArray *arrayMutableCopy = [array mutableCopy];
NSLog(@"array: %p", array);
NSLog(@"arrayCopy: %p", arrayCopy);
NSLog(@"arrayMutableCopy: %p", arrayMutableCopy);
//容器内的对象是浅拷贝,即它们在内存中只有一份
NSMutableString *testString = [array objectAtIndex:0];
[testString appendString:@" you"];
//三个数组的内容同时改变
NSLog(@"array[0]: %@", array[0]);
NSLog(@"arrayCopy[0]: %@", arrayCopy[0]);
NSLog(@"arrayMutableCopy[0]: %@", arrayMutableCopy[0]);
}
实现真正意义上的深复制
- (void)containerInstanceDeepCopy
{
NSArray *array = [NSArray arrayWithObjects:[NSMutableString stringWithString:@"Welcome"],@"to",@"Xcode",nil];
//数组内对象是指针复制
NSArray *deepCopyArray = [[NSArray alloc] initWithArray:array];
//真正以上的深复制,数组内对象是对象复制
NSArray *trueDeepCopyArray = [NSKeyedUnarchiver unarchiveObjectWithData:[NSKeyedArchiver archivedDataWithRootObject:array]];
NSLog(@"array: %p", array);
NSLog(@"deepCopyArray: %p", deepCopyArray);
NSLog(@"trueDeepCopyArray: %p", trueDeepCopyArray);
//改变array的第一个元素
[[array objectAtIndex:0] appendString:@" you"];
//只影响deepCopyArray数组的第一个元素
NSLog(@"array[0]: %@", array[0]);
NSLog(@"arrayCopy[0]: %@", deepCopyArray[0]);
//不影响trueDeepCopyArray数组的第一个元素,是真正意义上的深拷贝
NSLog(@"arrayMutableCopy[0]: %@", trueDeepCopyArray[0]);
}
自定义对象
在定义对象要实现拷贝,需要遵守NSCoping与NSMutableCoping协议,并实现以下方法
示例(自定对象Person的拷贝)
遵守协议,设置成员属性
@interface Person : NSObject <NSCopying, NSMutableCopying>
/**姓名*/
@PRoperty (nonatomic, copy) NSMutableString *name;
/**地址*/
@property (nonatomic, copy) NSString *address;
/**年龄*/
@property (nonatomic, assign) NSInteger age;
@end
重写初始化方法
- (instancetype)init
{
if (self = [super init])
{
self.name = [[NSMutableString alloc] initWithString:@"XiaoYaowang"];
self.address = @"空山新雨后";
self.age = 3;
}
return self;
}
实现- (id)copyWithZone:(NSZone *)zone
- (id)copyWithZone:(NSZone *)zone
{
Person *p = [[[self class] allocWithZone:zone] init];
p.name = [self.name copy];
p.address = [self.address copy];
p.age = self.age;
return p;
}
实现- (id)mutableCopyWithZone:(NSZone *)zone
- (id)mutableCopyWithZone:(NSZone *)zone
{
Person *p = [[[self class] allocWithZone:zone] init];
//注意,此处是mutableCopy方法
p.name = [self.name mutableCopy];
p.address = [self.address copy];
p.age = self.age;
return p;
}
---恢复内容结束---