我发现这个问题的文档不清楚:
假设您正在使用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 Object Retention”
所以......
“nib文件中的对象创建时保留计数为1,然后自动释放”很棒..
但是等等!读几句话......
但是,...如果没有可用的setter方法,则使用可用的setter方法或默认保留对象
他们在说什么?
他们是否意味着如果没有可用的setter(ivar,但没有属性),那就是 AGAIN RETAINED(除了前一条款中提到的“保留”)---或者,他们只是重复自己,即“默认保留对象”是他们之前刚刚讨论的“保留”(“保留计数为1然后自动释放”)。
为什么他们甚至会提到自动释放,如果不是这样的话呢?
确实 - 如果有人真正明确知道这个问题的答案...... 你怎么知道?!?你问过DTS,还是通过测试,或者?我建议,关键文档(刚刚粘贴)是非常不明确的。
再次 - 如果您有一个IBOutlet,但不是属性,则连接到“顶级”对象.. 您负责释放它吗?它保留了吗?在那种情况下?
就此而言....仅仅在情况(1)中,当BigView消失时,它会被释放吗?我当然会认为情况确实如此,但谁知道呢?
问题是如果你使用IBOutlet iVar会发生什么,而不是属性......
我愚蠢地从来没有想过这个/假设太多,有没有人有决定性的答案?干杯!!
为了记录,我做了一个测试项目。
事实上(令我惊讶的是)将IB元素连接到IBOutlet的行为实际上显然增加了一个保留。
(我只能从伪劣的文件中假设,在那种情况下你会特别得到:保留,自动释放,保留 - 导致一个保持平衡。)
所以,这就是答案。
我将发布演示项目。我也引导任何读者阅读下面的Jonah的答案,它完美地解释了setValue的行为:forKey:干杯
答案 0 :(得分:11)
我看不出是什么导致了这么多混乱,我认为“Nib Object Retention”文档准确地解释了会发生什么。让我们分解一下,然后看看会发生什么:
nib文件中的对象创建时保留计数为1,然后自动释放。
ClassLoadedFromNib *loadedObject = [[[ClassLoadedFromNib alloc] initWithCoder:coder] autorelease];
在重建对象层次结构时,UIKit使用setValue:forKey:方法重新建立对象之间的连接,
[filesOwner setValue:loadedObject forKey:nameOfIBOutlet];
如果没有可用的setter方法,使用可用的setter方法或默认保留该对象。
iOS中-setValue:forKey:
的默认行为大致是
//lazy pseudocode
if ([self respondsToSelector:@selector(@"setKeyName:")]) {
[self setKeyName:value];
}
else {
object_setIvar(self, _keyName, [value retain]);
}
有关更多详细信息,请参阅键值编程指南。除非您的文件所有者对象覆盖-setValue:forKey:
(或+accessInstanceVariablesDirectly
和-setValue:forUndefinedKey:
),否则期望按上述方式管理对象所有权。
如果为nib-file对象定义出口,则应始终定义用于访问该出口的setter方法(或声明的属性)。出口的Setter方法应保留其值,并且包含顶级对象的出口的setter方法必须保留其值以防止它们被释放。
允许nib加载将ivar直接设置为外部保留的对象令人困惑。不要那样做。为您的商店提供setter方法,以便明确加载对象的所有权。
如果未将顶级对象存储在出口中,则必须保留loadNibNamed:owner:options:方法返回的数组或数组内的对象,以防止这些对象过早释放。
未连接到插座的对象已自动释放。保留它们或从-loadNibNamed返回的数组:owner:options:如果您打算稍后尝试访问它们。
答案 1 :(得分:2)
这是一个有趣的问题,但由于文档含糊不清,我认为最好的计划(以及我认为Apple推荐的计划)是让所有商店保留属性。你确切知道在这种情况下会发生什么,并且没有理由做其他任何事情。
答案 2 :(得分:0)
案例1)如果对象没有被任何东西保留,它将在下一次自动释放池排放时被释放。
案例2)在上面提到的答案中,Jon Hess已经描述了(参考文档)在这种情况下Mac OS X和iOS之间的差异。
Jon Hess是正确还是Freeman正确?
在iOS案例中,Hess和Freeman都说该对象将被保留。他们之间没有矛盾。
强烈建议为所有网点设置setter方法:
Resource Programming Guide, Nib Files
如果为nib-file定义出口 对象,你应该总是定义一个 setter方法(或声明的属性) 用于访问该插座。二传手 出口的方法应保留 他们的价值......