实现拷贝,需要遵守以下两个协议
拷贝返回对象的种类
拷贝的种类
注意
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; }