如果您有IBOutlet但不是属性,是否保留?

Fat*_*tie 11 iphone cocoa-touch memory-management interface-builder nib

我发现这个问题的文档不清楚:

假设你正在使用iOS(不是Mac的情况,不需要提及差异).说严格是4.0+(不需要提及旧操作系统的差异).假设我们严格自动加载NIB.

假设你有一个UIViewController,BigView.假设NIB文件中有十几个所谓的"顶级"项目......可以是自定义控件,图像或其他任何内容.

假设您肯定会在应用程序运行期间多次明确创建然后摆脱BigView.所以:

对于NIB中的其中一个顶级项目,有三种可能性:

(1)根本没有任何形式的IBOutlet.

(2)你有一个连接的IBOutlet - 但不是属性.

(3)你确实有一个连接的IBOutlet属性(为了避免混淆,我们会说保留属性).

那么BigView发布时项目会发生什么?

在(3)的情况下,您必须明确释放.如果你不这样做,它将在视图消失后徘徊.没问题.

在(1)的情况下,我假设(但是任何人都可以确认?)当BigView消失时该项目将被释放.

在(2)的情况下,不清楚会发生什么.......

看看众所周知的参考链接:http://developer.apple.com/library/mac/#documentation/Cocoa/Conceptual/LoadingResources/CocoaNibs/CocoaNibs.html这是非常可疑的:

"在iOS中,nib加载代码使用setValue:forKey:方法重新连接每个插座.该方法类似地寻找一个合适的访问器方法和[所以如果没有一个发生的话会发生什么?告诉我们APPLE ...]当失败时,它会回到其他方式...... [GOOD GRIEF!]"

并查看此文档:http://developer.apple.com/library/mac/#documentation/Cocoa/Conceptual/LoadingResources/CocoaNibs/CocoaNibs.html并向下滚动到"Nib对象保留"

所以......

"nib文件中的对象创建时保留计数为1,然后自动释放" Fantastic ..

可是等等!读几句话......

但是,...如果没有可用的setter方法,则使用可用的setter方法或默认保留对象

他们在说什么?

它们是否意味着如果没有可用的setter(ivar,但没有属性),它是AGAIN RETAINED(除了他们在前一条款中提到的"保留") - 或者,他们只是重复自己,即"默认保留对象"与他们之前刚刚讨论的"保留"相同("使用保留计数1创建然后自动释放").

为什么他们甚至会提到自动释放,如果不是这样的话?

确实 - 如果有人真正明确知道这个问题的答案...... 你怎么知道的?!?你问过DTS,还是通过测试,或者?我建议,关键文档(只是粘贴)是非常不清楚的.

再次 - 如果你有一个IBOutlet,但不是一个属性,连接到"顶级"对象.. 你有责任释放它吗?它保留了吗?在那种情况下?

就此而言....仅仅在情况(1)中,当BigView消失时,它会被释放吗?我当然会认为情况确实如此,但谁知道呢?

问题是如果你使用IBOutlet iVar会发生什么,而不是属性......

我愚蠢地从来没有想过这个/假设太多,有没有人有决定性的答案?干杯!!


为了记录,我做了一个测试项目.

事实上(令我惊讶的是)将IB元素连接到IBOutlet的单纯行为实际上显然增加了一个保留.

(我只能从伪劣的文件中假设,在那种情况下你特别得到:保留,自动释放,保留 - 导致一个保持平衡.)

所以,这就是答案.

我将发布演示项目.我也将任何读者引导到下面的Jonah的答案,它完美地解释了setValue的行为:forKey:干杯

Jon*_*nah 11

我不知道是什么导致了这么多混乱,我认为"Nib Object Retention"文档准确地解释了会发生什么.让我们分解一下,然后看看会发生什么:

创建nib文件中的对象,保留计数为1,然后自动释放.

ClassLoadedFromNib *loadedObject = [[[ClassLoadedFromNib alloc] initWithCoder:coder] autorelease];
Run Code Online (Sandbox Code Playgroud)

但是,在重建对象层次结构时,UIKit使用setValue:forKey:方法重新建立对象之间的连接,

[filesOwner setValue:loadedObject forKey:nameOfIBOutlet];
Run Code Online (Sandbox Code Playgroud)

如果没有可用的setter方法,则默认使用可用的setter方法或保留对象.

-setValue:forKey:iOS中的默认行为是粗略的

//lazy pseudocode
if ([self respondsToSelector:@selector(@"setKeyName:")]) {
  [self setKeyName:value];
}
else {
  object_setIvar(self, _keyName, [value retain]);
}
Run Code Online (Sandbox Code Playgroud)

有关更多详细信息,请参阅键值编程指南.除非你的文件的所有者对象覆盖-setValue:forKey:(或+accessInstanceVariablesDirectly-setValue:forUndefinedKey:)期望对象所有权进行如上管理.


如果为nib-file对象定义出口,则应始终定义用于访问该出口的setter方法(或声明的属性).出口的setter方法应保留其值,并且包含顶级对象的出口的setter方法必须保留其值以防止它们被释放.

允许nib加载将ivar直接设置到外部保留的对象是令人困惑的.不要那样做.为您的商店提供setter方法,以便明确加载对象的所有权.


如果未将顶级对象存储在出口中,则必须保留loadNibNamed:owner:options:方法返回的数组或数组内的对象,以防止这些对象过早释放.

未连接到插座的对象已自动释放.保留它们或从-loadNibNamed返回的数组:owner:options:如果您打算稍后尝试访问它们.