如何在Objective-C中使用"copy"属性?

use*_*766 14 copy objective-c ios

我在线阅读了很多材料,这些材料都解释了人们何时应该使用" copy"代替" strong".

"复制属性是强大的替代品.它不是取得现有对象的所有权,而是创建您分配给属性的任何内容的副本,然后取得对该属性的所有权.只有符合NSCopying协议的对象才能使用此属性. ".

并且有很多示例代码显示使用"复制"时,原始值保持不变.

但是,我是新手Objective-C.我真的想知道如何使用新分配的值.带有"新值"的"新实例(副本)"在哪里?如果需要,是否需要任何其他方法来更改原始值?

如果有人可以分享这个部分的一个例子而不是一个证明原始值没有改变的例子,那将是很好的.

Cri*_*tik 10

copy属性在后台执行的操作是创建一个如下的setter:

- (void)setMyCopiedProperty:(MyClass *)newValue {
    _myCopiedProperty = [newValue copy];
}
Run Code Online (Sandbox Code Playgroud)

这意味着每当有人执行此类操作时object.myCopiedProperty = someOtherValue;,都会向其someOtherValue发送一条copy消息,告知其复制自己。然后,接收者将获得一个新的指针(假设copy已正确实现),除了接收者对象之外,没有人可以访问该指针。

您可以通过copy某种方式将其视为专有的:

  • 设置属性的客户端无权访问实际设置值
  • 接收者无法访问原始传递的值。

但是请注意以下警告:

  • 一个NSArray被复制的对象不会复制其对象,因此您可能最终认为a @property(copy) NSArray<MyClass *> *myProperty是安全的,但是尽管可以安全地修改数组本身,但数组所保存的对象共享相同的引用。同样适用于任何集合类(NSDictionaryNSSet,等)
  • 如果属性与自定义类匹配,则需要确保该copy方法完成其工作-即创建一个新对象。对于所有符合的Cocoa / CocoaTouch类,都会发生这种情况NSCopying,但是对于其他类,这可能会成立,也可能不会成立,这取决于实现方式(我自己还没有看到一个关于其copy方法的类,但是您永远都不知道)


Sur*_*han 5

尝试这个:

型号

@interface Model: NSObject

@property (nonatomic,strong)NSString *firstName;

@property (nonatomic,copy) NSString *lastName;

@end
Run Code Online (Sandbox Code Playgroud)

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);}


Output :
 1st Nslog = "test", "test" 
 2nd Nslog = "teststring", "test"
Run Code Online (Sandbox Code Playgroud)

  • 请解释您的答案,而不是仅发布代码。 (3认同)
  • @Sneha在第一个NSlog中将打印“ test”,“ test”,但是在第二个NSlog中将打印“ teststring”,“ test”,因为当对象是可变对象时需要“复制”。如果您现在需要该对象的值,并且不希望该值反映该对象的其他所有者所做的任何更改,请使用此值 (3认同)

Avi*_*Avi 1

类的实例是离散的副本。当您将类的实例指定为具有copy属性的属性值时,会创建该实例的克隆,并且该克隆将成为该属性的值。原始实例与其克隆之间没有关系,因此该属性根本无法访问原始实例。更改属性值的属性就是更改克隆。

笔记:

如果您为属性实现 setter copy,则您有责任确保它实际创建一个副本。与属性的所有属性一样,它们仅在编译器为您生成(合成)setter 和/或 getter 时才有意义。