我在网上阅读了很多材料,这些资料都解释了人们何时应该使用“copy
”代替“strong
”。
“copy属性是strong的替代品。它不是取得现有对象的所有权,而是创建您分配给属性的任何内容的副本,然后获取该属性的所有权。只有符合{{1}的对象} protocol可以使用这个属性......“
有很多示例代码显示使用“复制”时,原始值保持不变。
但是,我是NSCopying
的新手。我真的想知道如何使用新分配的值。带有“新值”的“新实例(副本)”在哪里?如果需要,是否需要任何其他方法来更改原始值?
如果有人可以分享这个部分的例子而不是证明原始值没有改变的那个,这将是很好的,这无处不在。
答案 0 :(得分:5)
幕后copy
属性的作用是创建一个这样的setter:
- (void)setMyCopiedProperty:(MyClass *)newValue {
_myCopiedProperty = [newValue copy];
}
这意味着每当有人执行此类object.myCopiedProperty = someOtherValue;
之类的操作时,someOtherValue
会向copy
发送一条消息,告知其自行复制。然后接收器获得一个新指针(假设正确实现copy
),除了接收者对象之外没有人可以访问。
您可以将copy
视为以某种方式排他性:
谨防注意事项:
NSArray
不会复制它的对象,因此您可能最终认为@property(copy) NSArray<MyClass *> *myProperty
是安全的,但是当阵列本身不被修改时,数组所拥有的对象分享相同的参考。任何集合类(NSDictionary
,NSSet
等)copy
方法完成它的工作 - 即创建新对象。对于符合NSCopying
的所有Cocoa / CocoaTouch类都会发生这种情况,但对于其他类,这可能与否,这取决于实现(我自己还没有看到一个关于copy
的类。方法,但你永远不知道)答案 1 :(得分:3)
试试这个:
Model.h
@interface Model: NSObject
@property (nonatomic,strong)NSString *firstName;
@property (nonatomic,copy) NSString *lastName;
@end
ViewController.m
-(void)viewWillAppear:(BOOL)animated{
[super viewWillAppear:animated];
Model *model = [[Model alloc]init];
NSMutableString *str = [[NSMutableString alloc]initWithString:@"test"];
model.firstName = str;
model.lastName = str;
NSLog(@"%@, %@", model.firstName, model.lastName);
[str appendString:@"string"];
NSLog(@"%@, %@ ", model.firstName, model.lastName);}
答案 2 :(得分:1)
类的实例是离散副本。当您将类的实例指定为具有copy
属性的属性的值时,将生成该实例的克隆,并且该克隆将成为该属性的值。原始实例与其克隆之间没有任何关系,因此该属性根本无法访问原始实例。更改属性值的属性正在更改克隆。
注意:强>
如果为copy
属性实现setter,则您有责任确保它实际创建副本。与属性的所有属性一样,它们只有在编译器为您生成(合成)setter和/或getter时才有意义。