我已经看到很多尝试在Stackoverflooooooow上回答这个问题,没有人对我感到满意。
我有一个Person
类,只有一个公共name
属性,其子类为NSObject
。在main
我跑:
Person *alex = [[Person alloc] init];
alex.name = @"alex"
NSLog(@"name: %@ %p", alex.name, alex.name");
将打印到控制台
2015-08-21 21:53:34.047 Test[29456:5960428] name: alex 0x108dfd640
我发现用于复制的两个方法都实现了copyWithZone:
协议的<NSCopying>
选择器,我把它放在Person
类中。
1)此选择器的第一个版本是:
- (id) copyWithZone:(NSZone *) zone
{
Person *personCopy = [[[self class] allocWithZone:zone] init];
personCopy.name = [self.name copyWithZone:zone];
// i've also tried: personCopy.name = [self.name copy];
return personCopy;
}
在主要的i中运行
Person *aCopyOfAlex = [alex copy]
NSLog(@"name: %@ %p", aCopyOfAlex.name, aCopyOfAlex.name");
记录
2015-08-21 21:53:34.047 Test[29456:5960428] name: alex 0x108dfd640
Person
副本实例 不同,但副本和原始名称属性指向相同的位置。
2)这个选择器的第二个版本使用了一个归档器(我想这需要一些时间 - 特别是如果我有很多属性要深入复制?)然后是unarchiver:
- (id) copyWithZone:(NSZone *) zone
{
Person *personCopy = [[[self class] allocWithZone:zone] init];
NSData *buffer = [NSKeyedArchiver archivedDataWithRootObject:self.name];
personCopy.name = [NSKeyedUnarchiver unarchiveObjectWithData:buffer];
return personCopy;
}
在主要我再次运行
Person *aCopyOfAlex = [alex copy]
NSLog(@"name: %@ %p", aCopyOfAlex.name, aCopyOfAlex.name");
记录
2015-08-21 21:53:34.047 Test[29456:5960428] name: alex 0x7fa80969e4a0
这次Person
副本实例和名称属性都指向不同的位置。
谢谢!
答案 0 :(得分:2)
你的第一段代码没有错。你看到的是用字符串完成的优化。由于您从一个不可变的字符串文字开始,复制它只会让您返回相同的对象。这不是问题,因为它是不可变的。
您对Person copyWithZone:
的第二次实施是过度的。不要为存档而烦恼。
答案 1 :(得分:0)
虽然我不得不同意@rmaddy关于第二个对于这个确切案例而言过度杀戮的事情,但它是唯一一个(从你发布的两个)中执行深层复制的案例。
请参阅What is the difference between a deep copy and a shallow copy?,了解深度复制的详细说明。
如果你有一个可变属性说NSMutableArray *addresses
,第一种方法会让你有两个Person
实例共享相同的NSMutableArray
个实例,这意味着如果你改变地址,你会看到两个Person实例中的更改,因为它们确实共享相同的数组。
请注意,第二个将取决于Person中的属性是否确实可以存档。