为IBOutlet Work的只读属性是否会更好?

问题描述:

在代码,我继承,我已经看到了以下内容:为IBOutlet Work的只读属性是否会更好?

@property (readonly) IBOutlet UIImageView * bgImage; 

当我想到一个保留的内存模型,如:

@property (readonly, retain) IBOutlet UIImageView * bgImage; 

我很困惑,为什么第一属性定义工作不会造成问题。

此外,还有在一个dealloc中作为release你所期望的一样:

-(void)dealloc 
{ 
    [_bgImage release]; 
    [super dealloc]; 
} 

我会很感激,如果有人能想出这种解释。我已经和最初的开发者谈过了,他正在尝试写出更简洁的代码,这就是为什么他在内存模型中忽略了retain(似乎不必要)。

我不知道是否IBOutlet基本上对待像伊娃IBOutlet声明,因为它是只读的(没有设置使用,因此默认分配内存模型没有区别)。

如果IBOutlet中从未预期发生变化,会使用一个只读属性,无记忆模式实际上是定义性的最好方法是什么?

iOS上的笔尖加载器会在笔尖的对象,然后自动释放他们。当它建立连接到网点时,它使用setValue:forKey:,它将调用该密钥的setter方法。如果没有设定器被定义,诸如当IBOutletreadonly属性,所述对象被分配之前保留反正。 (这是Managing Nib Objects in iOS资源编程指南中的意译。)

所以在实际事实上,插座是否被声明为retainassign与出口的对象所拥有的另一端对象。它可以通过setter方法保留,也可以在没有找到setter时被setValue:forKey:保留。由于在第二种情况下没有其他可能的所有者,因此您可以认为带有插座的对象是所有者。因此,笔尖中的物体应该在dealloc中释放。

我同意你应该通过改变属性属性来包括retain这个内存条件。*是否它是readonly似乎没有什么区别(但是,见下文)。从概念上讲,是的,该对象是只读的,因此是否明确标记它取决于您是否认为这是一个IBOutlet这一事实适当记录。

更新:下面 Paul.s的评论促使我做一个快速测试。我创建了一个UIView子类,它记录了它的alloc,retain,,releaseautorelease调用,将它的一个实例粘贴到笔尖中,并通过属性给应用程序委托人IBOutlet

当手动计算参考计数活动时,当物业为(readwrite, assign)时,实例出现净0计数。当物业被宣布为推荐方式时,它是净+1,(readwrite, retain)也是,当时是(readonly, assign)。所有这些都非常符合预期 - 当它是(readwrite, assign)时,分配设置器用于建立连接,并且不进行保留。当它是readonly时,连接机制退回到自己的保留状态。

最有趣的是,当我试图改变这一观点与物业的背景色崩溃的应用程序中声明(readwrite, assign)(即,当它可能已释放),我看到了retain弹出一个最后一次通话。

我想这是归结为:遵循苹果的建议 - 他们知道幕后发生了什么,并且(禁止错误)不会误导你。

(另外一件事情就是,一如既往地担心绝对引用计数并不会非常有用 - 计数一直达到6,一次就超过了二十次调用到retainrelease - 你只需要担心的保留和您直接导致发行)


*当然,这ARC下改变。我解释的信息在本章的“遗留模式”部分。在ARC下,建议IBOutlets的值为weak,除非它们是顶层的,在这种情况下,它们应该是strong。这样做意味着您依靠视图层次结构(保留其子视图的视图)来维护自己。

+0

'这个出口是否被声明为保留或分配,另一端的对象是否被带有出口的对象所拥有(这不是很清楚),只有当它被设置为'readonly'时才这样吗?如果它是'(分配,读写)'那么肯定会使用非保留的setter,并且不会保留'' - 我只提到,因为它是你答案的唯一部分,这有点含糊 –

+0

我认为是......这似乎是它所说的。 –

+2

@ Paul.s:看到我的更新 - 我决定手工计算参考活动,结果是,我认为,有启发性。 –

我已经报告了一个苹果的错误,如果你创建IBOutlet实例变量而不是属性,那Xcode仍然会自动在dealloc等中创建发行版。iOS应用程序的Xcode似乎总是为IBOutlet创建版本,无论它是否正确。

人员我不喜欢属性IBOutlet,因为它意味着您将它们声明为readwrite,这意味着它们被记录为readwrite,但大多数情况下(几乎总是),IBOutlet在概念上应该是只读的。显然,他们必须先读写才能设置。

+0

您可以在公共接口中声明'@property(nonatomic,只读)'并在类扩展中声明'@property(nonatomic)IBOutlet'。 –