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

时间:2022-04-18 05:46:39

I have read through many materials online which all explain when people should use "copy" instead of "strong".

我在线阅读了许多材料,这些材料都解释了人们何时应该使用“复制”而不是“强”。

"The copy attribute is an alternative to strong. Instead of taking ownership of the existing object, it creates a copy of whatever you assign to the property, then takes ownership of that. Only objects that conform to the NSCopying protocol can use this attribute..."

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

And there are plenty of example codes showing when using "copy", the original value stays the same.

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

However, I'm new to Objective-C. I really want to know how to use the newly assigned value. Where is the "new instance(copy)" with the "new value"? Do I need any additional methods to change the original value if I want to?

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

It will be great if someone can share an example for this part not the one proving the original value is not changed, which is everywhere.

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

3 个解决方案

#1


3  

What the copy attribute does behind the scenes is to create a setter like this:

幕后复制属性的作用是创建一个这样的setter:

- (void)setMyCopiedProperty:(MyClass *)newValue {
    _myCopiedProperty = [newValue copy];
}

this means that whenever someone does something like this object.myCopiedProperty = someOtherValue;, the someOtherValue is sent a copy message telling it to duplicate itself. The receiver gets then a new pointer (assuming copy is correctly implemented), to which no-one excepting the receiver object has access to.

这意味着每当有人做类似这个对象的事情.myCopiedProperty = someOtherValue;时,someOtherValue会发送一条复制消息,告诉它复制自己。然后接收器获得一个新指针(假设正确实现了复制),除了接收器对象之外没有人可以访问。

You can look at copy as being exclusive in some kind of way:

您可以通过某种方式将副本视为独占:

  • the clients that set the property don't have access to the actual set value
  • 设置该属性的客户端无权访问实际的设置值

  • the receiver doesn't have access to the original passed value.
  • 接收方无法访问原始传递的值。

Beware of the caveats, though:

但请注意警告:

  • a copied NSArray doesn't copy it's objects, so you might end up thinking that a @property(copy) NSArray<MyClass *> *myProperty is safe, however while the array itself is safe from being modified, the objects held by the array share the same reference. Same is true for any collection class (NSDictionary, NSSet, etc)
  • 复制的NSArray不会复制它的对象,因此您可能最终认为@property(复制)NSArray * myProperty是安全的,但是当阵列本身不被修改时,数组所拥有的对象分享相同的参考。任何集合类(NSDictionary,NSSet等)都是如此

  • if the property matches to a custom class you need to make sure the copy method does it's job - i.e. creating a new object. This happens for all Cocoa/CocoaTouch classes that conform to NSCopying, however for other classes this might or not be true, depending on implementation (myself I didn't saw yet a class that lies about its copy method, however you never know)
  • 如果属性与自定义类匹配,则需要确保复制方法完成它的工作 - 即创建新对象。对于符合NSCopying的所有Cocoa / CocoaTouch类都会发生这种情况,但对于其他类,这可能与否,这取决于实现(我自己还没有看到一个关于其复制方法的类,但是你永远不知道)

#2


1  

An instance of a class is a discrete copy. When you assign an instance of a class to be the value of a property with the copy attribute, a clone of that instance is made and that clone becomes the value of the property. There is no relationship between the original and its clone, so the property does not have access to the original instance at all. Changing an attribute of the property's value is changing the clone.

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

Note:

If you implement the setter for a copy property, it is your responsibility to ensure it actually creates a copy. As is true with all the attributes for a property, they only have meaning when the compiler is generating (synthesizing) the setter and/or getter for you.

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

#3


1  

Try this:

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

#1


3  

What the copy attribute does behind the scenes is to create a setter like this:

幕后复制属性的作用是创建一个这样的setter:

- (void)setMyCopiedProperty:(MyClass *)newValue {
    _myCopiedProperty = [newValue copy];
}

this means that whenever someone does something like this object.myCopiedProperty = someOtherValue;, the someOtherValue is sent a copy message telling it to duplicate itself. The receiver gets then a new pointer (assuming copy is correctly implemented), to which no-one excepting the receiver object has access to.

这意味着每当有人做类似这个对象的事情.myCopiedProperty = someOtherValue;时,someOtherValue会发送一条复制消息,告诉它复制自己。然后接收器获得一个新指针(假设正确实现了复制),除了接收器对象之外没有人可以访问。

You can look at copy as being exclusive in some kind of way:

您可以通过某种方式将副本视为独占:

  • the clients that set the property don't have access to the actual set value
  • 设置该属性的客户端无权访问实际的设置值

  • the receiver doesn't have access to the original passed value.
  • 接收方无法访问原始传递的值。

Beware of the caveats, though:

但请注意警告:

  • a copied NSArray doesn't copy it's objects, so you might end up thinking that a @property(copy) NSArray<MyClass *> *myProperty is safe, however while the array itself is safe from being modified, the objects held by the array share the same reference. Same is true for any collection class (NSDictionary, NSSet, etc)
  • 复制的NSArray不会复制它的对象,因此您可能最终认为@property(复制)NSArray * myProperty是安全的,但是当阵列本身不被修改时,数组所拥有的对象分享相同的参考。任何集合类(NSDictionary,NSSet等)都是如此

  • if the property matches to a custom class you need to make sure the copy method does it's job - i.e. creating a new object. This happens for all Cocoa/CocoaTouch classes that conform to NSCopying, however for other classes this might or not be true, depending on implementation (myself I didn't saw yet a class that lies about its copy method, however you never know)
  • 如果属性与自定义类匹配,则需要确保复制方法完成它的工作 - 即创建新对象。对于符合NSCopying的所有Cocoa / CocoaTouch类都会发生这种情况,但对于其他类,这可能与否,这取决于实现(我自己还没有看到一个关于其复制方法的类,但是你永远不知道)

#2


1  

An instance of a class is a discrete copy. When you assign an instance of a class to be the value of a property with the copy attribute, a clone of that instance is made and that clone becomes the value of the property. There is no relationship between the original and its clone, so the property does not have access to the original instance at all. Changing an attribute of the property's value is changing the clone.

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

Note:

If you implement the setter for a copy property, it is your responsibility to ensure it actually creates a copy. As is true with all the attributes for a property, they only have meaning when the compiler is generating (synthesizing) the setter and/or getter for you.

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

#3


1  

Try this:

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