使用ARC为ios声明readonly属性的正确方法是什么

时间:2012-05-22 01:25:18

标签: objective-c object properties automatic-ref-counting readonly

我是iOS开发的新手,从未处理过手动引用计数(保留,释放,自动释放)。因此,我对ARC的神奇表现并不了解。

我以为我理解了,直到有人询问我应该将哪种类型的所有权(weakstrongassign等)赋予指向对象的只读属性,例如:

@property (readonly,nonatomic) NSString* name;

我在这里读到 离开strong / weak的{​​{3}}除非您在@synthesize财产时指定支持变量,否则实际上不会编译;我恰好正在指定这样的支持ivar:

@synthesize name = _name;

现在我明白变量的默认'生命周期限定符'很强,从这里开始:Questions about a readonly @property in ARC

所以简而言之 - 我间接地将我的属性定义为(readonly,nonatomic,strong),因为_name ivar被隐式声明为__strong

我有几个问题:

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

    < / LI>
  2. 在这种情况下是否有其他有意义的修饰符,例如copyassign

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

  4. 谢谢!

    修改

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

    • 对于非NSObject *类型(int,float,void *等),请使用(readonly, assign)
    • 对于对象指针,使用(readonly, strong)(readonly, copy) - 这些函数对于readonly属性的功能相同,但如果扩展/子类并将属性重新声明为readwrite,则可能需要复制语义。
    • 对于对象指针,(readonly, weak)只有在您要在该属性中存储已经很弱的指针时才有意义(该指针必须在其他位置强,否则该对象将被释放)。

3 个答案:

答案 0 :(得分:12)

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

  2. assign与标量值一起使用,是默认的setter。如果您想自动复制对象并将指针设置为副本而不是指向原始对象,则copy是有意义的。如果您有特殊需要(通常是因为您不希望对象在您身上发生变异),这样做才有意义。

  3. 您提供的链接显示__strong是默认值(因此您无需指定),指的是变量 声明的属性。声明属性的默认值为assign,因此它肯定会有所作为。但是,如果你想要assign,那么无论你是否指定它都没有区别(除了要明确它是你想要的)。 编辑:但是,正如Jacques指出的那样,LLVM 3.1正在发生变化,默认情况下 正在将 assign更改为{{ 1}}。在这种情况下,无论您是否指定strong都没有区别,如果您愿意,可以将其删除。我个人认为拼出它是好的(特别是因为不同版本之间存在冲突)所以每个看代码的人都在同一页面上。其他人可能在这一点上不同意。 :)

  4. 我建议在这里阅读 Objective-C编程语言声明的属性部分:strong

答案 1 :(得分:7)

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

目前的情况是,该属性的所有其他属性必须保持一致。可以想象编译器可以放宽这个要求。 (有些人认为这是一个错误。)无论如何,这是宣布具有readonlystrong或弱所有权属性的copy属性的一个原因,以便它与{{{ 1}}重新声明其他地方。

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

答案 2 :(得分:0)

这两行代码对我有用:

.h文件:

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

.m文件:

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