Ios 如何使用;“复制”;Objective-C中的属性?

Ios 如何使用;“复制”;Objective-C中的属性?,ios,objective-c,copy,Ios,Objective C,Copy,我在网上读了很多资料,都解释了人们什么时候应该使用“copy”而不是“strong” “复制属性是strong的替代。它不获取现有对象的所有权,而是创建您分配给属性的任何内容的副本,然后获取该属性的所有权。只有符合NSCopying协议的对象才能使用此属性…” 还有很多示例代码显示,当使用“复制”时,原始值保持不变 但是,我不熟悉Objective-C。我真的想知道如何使用新分配的值。带有“新值”的“新实例(副本)”在哪里?如果我想更改原始值,是否需要其他方法 如果有人能为这一部分分享一个例子,

我在网上读了很多资料,都解释了人们什么时候应该使用“
copy
”而不是“
strong

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

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

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


如果有人能为这一部分分享一个例子,而不是证明原始值没有改变的例子,那就太好了,因为它无处不在。

类的实例是一个离散副本。当使用
copy
属性将类的实例指定为属性的值时,将生成该实例的克隆,该克隆将成为属性的值。原始实例与其克隆之间没有关系,因此该属性根本无权访问原始实例。更改属性值的属性就是更改克隆

注意:


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

copy属性在幕后的作用是创建如下setter:

- (void)setMyCopiedProperty:(MyClass *)newValue {
    _myCopiedProperty = [newValue copy];
}
这意味着每当有人做这样的事情时,
object.myCopiedProperty=someOtherValue
,则会向
someOtherValue
发送一条
copy
消息,告知其复制自身。然后,接收方获得一个新指针(假设正确实现了
copy
),除接收方对象外,没有人可以访问该指针

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

  • 设置属性的客户端没有访问实际设置值的权限
  • 接收方无权访问原始传递的值
不过,请注意以下注意事项:

  • 复制的
    NSArray
    不会复制其对象,因此您可能会认为
    @property(copy)NSArray*myProperty
    是安全的,但是,虽然数组本身不会被修改,但数组持有的对象共享相同的引用。对于任何集合类(
    NSDictionary
    NSSet
    等)也是如此
  • 如果属性与自定义类匹配,则需要确保
    copy
    方法执行其任务,即创建新对象。所有符合
    NSCopying
    的Cocoa/CocoaTouch类都会发生这种情况,但是对于其他类,这可能是真的,也可能不是真的,这取决于实现(我自己还没有看到一个类对其
    copy
    方法撒谎,但你永远不知道)
试试这个:

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


Output :
 1st Nslog = "test", "test" 
 2nd Nslog = "teststring", "test"

本质上,由于您现在有一个副本,因此您没有对原始对象的引用,因此您无法更改它。@Paulw11“您没有对原始对象的引用”是什么意思?我在网上找到了使用原始引用注销原始值的示例。你能举个例子吗?我还对新值的位置以及如何使用感到困惑如果我将
a
赋值给a
copy
属性
b
,那么setter代码所做的就是有效地
b=[a copy]
,因此现在b是一个新字符串。如果我更改
a
,则
b
不会发生任何变化,因为b是一个副本。类似地,如果我更改
b
a
@Sneha在第一个NSlog中不会发生任何变化,它将打印“test”、“test”,但在第二个NSlog中,它将打印“teststring”、“test”,因为当对象可变时需要“copy”。如果需要对象当前的值,并且不希望该值反映对象的其他所有者所做的任何更改,请使用此选项