18

一般来说,我是 iOS 开发的新手,从未处理过手动引用计数(保留、释放、自动释放)。因此,我对魔术 ARC 的表现不太了解。

我以为我明白了,直到有人问我应该为指向对象的只读属性赋予什么类型的所有权( weak, strong,等),例如:assign

@property (readonly,nonatomic) NSString* name;

我在这里阅读了 有关 ARC中只读 @property 的问题,除非您在属性时指定支持变量,否则不会实际编译strong/ ;我只是碰巧指定了一个像这样的支持 ivar:weak@synthesize

@synthesize name = _name;

现在我知道变量的默认“生命周期限定符”很强大,从这里开始:http: //developer.apple.com/library/ios/releasenotes/ObjectiveC/RN-TransitioningToARC/Introduction/Introduction.html#//apple_ref /doc/uid/TP40011226-CH1-SW4

所以长话短说 - 我间接地将我的属性定义(readonly,nonatomic,strong)_nameivar 被隐式​​声明为__strong.

我有几个问题:

  1. 是否strong使用正确的生命周期限定符?我假设是这样,否则支持 my 的对象NSString*将不会在任何地方拥有,因此会被自动释放(来自 Java 领域这是有道理的,因为默认情况下所有引用都是强的)。

  2. 在这种情况下是否有任何其他修饰符有意义,例如copyor assign

  3. 将属性声明为(readonly,nonatomic,strong)并对使用该属性(readonly,nonatomic)的代码有任何影响吗?例如。在没有关键字的情况下声明它会导致对象指针存储为属性将存储在指针中的位置吗?strong__unsafe_unretainedstrong__strong

谢谢!

编辑

据我所知,以下适用于只读属性:

  • 对于非 NSObject* 类型(int、float、void* 等),请使用(readonly, assign).
  • 对于对象指针,使用(readonly, strong)or (readonly, copy)- 这些功能与只读属性相同,但如果您扩展/子类并将属性重新声明为readwrite.
  • 对于对象指针,(readonly, weak)只有当您要在该属性中存储一个已经很弱的指针时才有意义(该指针在其他地方必须是强的,否则对象将被释放)。
4

3 回答 3

12
  1. strong如果您想保持对您所指向的任何内容的强(拥有)引用,则使用是正确的。通常,您确实需要强引用,但为了防止循环引用(特别是在父/子关系中,如果父指向子,子指向父,它们将永远不会被释放)有时需要使用弱引用. 此外,如果你想保留一个指向你不拥有的对象的指针,但希望它只在它存在时才有效,那么你想使用弱指针,因为当它被所有者释放时,你的指针将自动设置为nil并且不会指向不应该指向的内存。

  2. assign与标量值一起使用,并且是默认设置器。 copy如果您想自动制作对象的副本并将指针设置为副本而不是指向原始对象,那么这是有意义的。仅当您有特定需求时才有意义(通常是因为您不希望对象在您身上发生变异)。

  3. 您提供的链接显示 __strong 是默认值(因此您不需要指定它)是指变量不是声明的属性。声明属性的默认值是assign这样,它肯定会有所作为。但是,如果您想要assign,无论您是否指定它都没有区别(只是为了清楚它是您想要的)。 编辑:但是,正如 Jacques 所指出的,这随着 LLVM 3.1 的变化而变化,默认值从更改assignstrong。在这种情况下,您是否指定绝对没有区别strong如果您愿意,可以将其排除在外。我个人认为最好把它拼出来(特别是因为不同版本之间存在冲突),以便每个看代码的人都在同一页面上。不过,其他人可能不同意这一点。:)

我建议在这里阅读Objective-C 编程语言的声明属性部分:.<document removed by Apple with no direct replacement>

于 2012-05-22T01:41:10.303 回答
7

另外一点:属性可以从readonlyto重新声明readwrite。例如,子类可以将超类的只读属性变为可读写,类似于有多少 Cocoa 类具有添加可变性的子类。同样,一个属性可能是公开只读的,但该类可以将其重新声明为可读写,以便在类扩展中内部使用。因此,当类设置自己的属性时,它可以利用合成的 setter 正确地进行内存管理并发出适当的 Key-Value Observing 更改通知。

按照目前的情况,该属性的所有其他属性都必须保持一致。可以想象编译器可以放宽这个要求。(有些人认为这是一个错误。)无论如何,这是声明readonly具有所有权属性(如strongcopy或 weak)的属性的一个原因——这样它就可以匹配readwrite其他地方的重新声明。

关于您的问题 3,您是否在问所有权限定符是否会影响调用 getter 的代码?不,它没有。

于 2012-05-22T03:54:18.370 回答
0

这两行代码对我有用:

.h 文件:

@property (nonatomic, readonly, copy) NSString *username;

.m 文件:

@property (nonatomic, readwrite, copy) NSString *username;
于 2015-08-21T19:45:23.437 回答