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


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

假设您正在使用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,但没有属性),那就是它 再次 保留(除了他们刚刚在前一条款中提到的“保留”)---或者,他们只是重复自己,即“默认保留对象”与他们之前所说的“保留”相同(“使用保留计数1创建,然后自动释放“)。

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

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

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

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

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

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


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

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

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

所以,这就是答案。

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


1788
2018-04-02 12:57


起源

非常感谢你。我真的想知道同样的问题!阅读苹果文档后我感到非常困惑,所以我完全不确定该相信什么。还要感谢Jonah的澄清。 - Buju
这很奇怪 - 我同意你的看法。投票的谢谢,因为那个给了我“超级大国”或者这个网站上的东西!我是世界之王! - Fattie


答案:


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

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

ClassLoadedFromNib *loadedObject = [[[ClassLoadedFromNib alloc] initWithCoder:coder] autorelease];

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

[filesOwner setValue:loadedObject forKey:nameOfIBOutlet];

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

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

//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:如果您打算稍后尝试访问它们。


11
2018-04-02 19:52



嘿Joneh - 简而言之,这是对setValue的一个很好的解释:forKey:行为,谢谢。 (正如我所描述的那样,doco。严重缺陷......没有你我们会被塞满。)干杯! - Fattie


这是一个有趣的问题,但由于文档含糊不清,我认为最好的计划(以及我认为Apple推荐的计划)是让您的所有商店保留属性。你确切知道在这种情况下会发生什么,并且没有理由做任何其他事情。


2
2018-04-02 13:34



我没有dv,但是如果你需要看到它而且你想要吸气/装定者,你肯定只需要做一些出路吗? - ingh.am
如果你需要一个插座,那是因为你计划保留对从nib文件创建的东西的引用。使用属性来管理该引用可以避免上面提出的各种问题,并且还可以使内存管理更容易。当然,你可以直接使用ivar,但任何财产都是如此。也许你的意思是,当你打算使用self以外的对象来改变相关值时,你可能只使用一个属性,但这正是从nib加载对象时发生的情况。 - Caleb
@Joe Blow,我认为这是一个有趣的问题,但由于这样的话题往往会让初学者感到困惑,所以我想把最好的实用解决方案放在那里。我知道我发布的内容并不是您所寻找的答案,如果有人因为这个原因选择了这个答案就行了。 - Caleb
使用属性真的可以提高性能吗?我的印象是它为你提供了一个吸气剂和固定器...我从不使用属性,除非我也有,我从来没有发现任何性能上的差异(虽然我可能是错的)。编辑:哦等等,你的意思是性能,因为不使用属性获得稍快的性能?如果是这样,我理解!!我也这样做! - ingh.am
@Joe是的,我们在同一页面上...根据我的经验,我只在需要时使用属性,因为a)我总是被教导在需要时创建吸气剂和制定者b)我不能被诅咒这样做每个var! - ingh.am


情况1)如果对象未被任何东西保留,它将在下一次自动释放池排放时被释放。

案例2)在上面提到的答案中,Jon Hess已经描述了(参考文档)在这种情况下Mac OS X和iOS之间的差异。

乔恩赫斯是正确的还是弗里曼正确的?

在iOS案例中,Hess和Freeman都说该对象将被保留。他们之间没有矛盾。

仍然强烈建议为所有网点设置setter方法:

资源编程指南,Nib文件

如果为nib-file定义出口   对象,你应该总是定义一个   setter方法(或声明的属性)   用于访问该插座。二传手   出口的方法应保留   他们的价值......


0
2018-04-02 13:48



是的,它被保留了,你应该在它完成后释放它(在 dealloc通常情况下)。实际上我过去使用过这种方法,但现在我使用了这个属性,因为它对我代码的未来维护者来说不那么混乱了。 - hoha
嗨,Hoha。谢谢你的指导。事实上,我做了一个测试项目,它证明了这种情况。我会发布它。我非常惊讶的是,仅将IB元素连接到IBOutlet的行为实际上增加了一个保留。再次感谢和欢呼!对不起,有些白痴投了你的评论! - Fattie