如果您有 IBOutlet,但没有属性,那么它是否保留?

发布于 2024-10-30 00:21:00 字数 2142 浏览 1 评论 0原文

我发现有关此问题的文档不清楚:

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

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

假设您肯定会在应用程序运行期间多次显式创建然后删除 BigView。因此:

对于 NIB 中的这些顶级项目之一,存在三种可能性

(1) 您根本没有任何类型的 IBOutlet。

(2) 您确实有一个连接的 IBOutlet - 但不是一个属性。

(3) 您确实有一个已连接的 IBOutlet 属性(为了避免混淆,我们称其为保留属性)。

那么当 BigView 发布时,该项目会发生什么情况呢?

对于 (3) 的情况,显然您必须明确释放。如果不这样做,它会在视图消失后继续存在。没问题。

对于 (1),我假设(但有人能真正确认吗?)该项目将在 BigView 消失后发布。

对于(2),尚不清楚会发生什么......

查看众所周知的参考链接:https://developer.apple.com/library/archive/documentation/Cocoa/Conceptual/LoadingResources/CocoaNibs/CocoaNibs .html 非常可疑:

“在 iOS 中,笔尖加载代码使用 setValue:forKey: 方法重新连接每个插座。该方法类似地寻找适当的访问器方法,并且[如果没有的话会发生什么?告诉我们苹果。 ..] 当失败时求助于其他方法...[好悲伤!]”

并向下滚动到“Nib 对象保留”:

“nib 文件中的对象创建时保留计数为 1,然后自动释放” 太棒了..

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

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

他们在说什么?

他们的意思是,如果没有可用的setter(ivar,但没有属性),那么它会再次保留(除了他们在上一条中提到的“保留”之外)——或者,是他们只是重复自己,即“默认情况下保留对象”与他们之前谈论的“保留”相同(“使用保留计数为1创建,然后自动释放”)。

如果情况并非如此,他们为什么还要提到自动释放呢?

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

再说一次 - 如果您有一个 IBOutlet,但不是属性,连接到“顶级”对象..您负责释放它吗?在那种情况下它会被保留吗?

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

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

我之前愚蠢地从未考虑过这个/假设太多,有人有决定性的答案吗?干杯!!


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

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

(我只能从劣质文档中假设,在这种情况下,你会得到具体的结果:Retain、Autorelease、Retain - 导致一个保留平衡。)

所以,这就是答案。

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

I find the documentation on this issue to be unclear:

Say you are working with iOS (NOT the Mac case, no need to mention the differences). Say it is strictly 4.0+ (no need to mention differences in old OS). Say we are loading the NIB strictly automatically.

Say you have a UIViewController, BigView. Say there are a dozen so-called "top-level" items in the NIB file...could be custom controls, images, or anything else.

Say you are definitely going to explicitly create and then get rid of BigView a number of times during the app's run. So:

For one of these top-level items in the NIB, there are three possibilities:

(1) You do not have any sort of IBOutlet for it, at all.

(2) You do have a connected IBOutlet - but not a property.

(3) You do have a connected IBOutlet property (to avoid confusion, we'll say a retain property).

So what happens to the item when BigView is released?

In the case of (3) it seems clear that you must release explicitly. If you do not, it will hang around after the view is gone. No problem.

In the case of (1) I assume (but can anyone actually confirm?) that the item will be released when BigView is gone.

In the case of (2) it's not clear what happens.......

Looking at the well-known reference link: https://developer.apple.com/library/archive/documentation/Cocoa/Conceptual/LoadingResources/CocoaNibs/CocoaNibs.html it is very dubious:

"In iOS, the nib-loading code uses the setValue:forKey: method to reconnect each outlet. That method similarly looks for an appropriate accessor method and [SO WHAT HAPPENS IF THERE ISN'T ONE?? TELL US APPLE...] falls back on other means when that fails...[GOOD GRIEF!]"

And scroll down to "Nib Object Retention":

"Objects in the nib file are created with a retain count of 1 and then autoreleased" Fantastic..

But wait! Read on a few words...

however, ... which uses the available setter method or retains the object by default if no setter method is available

What are they talking about?

Do they mean that if no setter is available (ivar, but no property), that it is AGAIN RETAINED (other than the "retain" they just mention in the previous clause) --- or, are they just repeating themselves, i.e. the "retains the object by default" is the same "retain" they were talking about immediately previously ("created with a retain count of 1 and then autoreleased").

And why would they even mention the autorelease if that's not what happens?

Indeed -- if anyone actually specifically knows the answer to this question ...... how do you know?!? Did you ask DTS, or through testing, or? I suggest, the key documentation (just pasted in) is aggressively unclear.

Again - if you have an IBOutlet, but not a property, connected to a "top-level" object .. are you responsible for releasing it? Is it retained? in that situation?

For that matter .... merely in situation (1) is it absolutely the case that the thingy will be released when BigView goes away? I would certainly assume this is the case, but who knows?

The question is what happens if you DO use an IBOutlet iVar, but NOT a property...

I've foolishly never thought about this before / assumed too much, does anyone have the decisive answer? Cheers!!


For the record I have made a test project.

In fact (surprisingly to me) the mere act of connecting an IB element to an IBOutlet in fact apparently adds one retain.

(I can only assume from the shoddy docu, in that situation you get specifically: Retain, Autorelease, Retain - leading to one retain on balance.)

So, that's the answer.

I will post the demo project. I also direct any readers to Jonah's answer below which flawlessly explains the behavior of setValue:forKey: Cheers

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

舟遥客 2024-11-06 00:21:00

我不明白是什么导致了如此多的混乱,我认为“Nib 对象保留”文档准确地解释了发生的情况。让我们分解一下并看看会发生什么:

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 文件对象定义插座,则应始终定义用于访问该插座的 setter 方法(或声明的属性)。出口的 setter 方法应保留其值,包含顶级对象的出口的 setter 方法必须保留其值以防止它们被释放。

允许 nib 加载将 ivar 直接设置为外部保留的对象是令人困惑的。不要那样做。为您的 Outlet 提供 setter 方法,以便加载对象的所有权清晰可见。


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

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

I don't see what causes so much confusion, I think the "Nib Object Retention" documentation explains exactly what happens. Let's break it down and walk through what happens:

Objects in the nib file are created with a retain count of 1 and then autoreleased.

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

As it rebuilds the object hierarchy, however, UIKit reestablishes connections between the objects using the setValue:forKey: method,

[filesOwner setValue:loadedObject forKey:nameOfIBOutlet];

which uses the available setter method or retains the object by default if no setter method is available.

The default behavior of -setValue:forKey: in iOS is roughly

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

See the key-value programming guide for even more detail. Unless your file's owner object overrides -setValue:forKey: (or +accessInstanceVariablesDirectly and -setValue:forUndefinedKey: ) expect object ownership to be managed as above.


If you define outlets for nib-file objects, you should always define a setter method (or declared property) for accessing that outlet. Setter methods for outlets should retain their values, and setter methods for outlets containing top-level objects must retain their values to prevent them from being deallocated.

Allowing nib loading to set ivar directly to externally retained objects is confusing. Don't do that. Provide setter methods for your outlets so the ownership of the loaded object is clear.


If you do not store the top-level objects in outlets, you must retain either the array returned by the loadNibNamed:owner:options: method or the objects inside the array to prevent those objects from being released prematurely.

Objects not connected to outlets have been autoreleased. Retain them or the array returned from -loadNibNamed:owner:options: if you are going to try to access them later.

淡淡離愁欲言轉身 2024-11-06 00:21:00

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

It's an interesting question, but because the documentation is ambiguous I think the best plan (and the one that I believe is recommended by Apple) is to make all your outlets retain properties. You know exactly what happens in that case, and there's little reason to do anything else.

风筝在阴天搁浅。 2024-11-06 00:21:00

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

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

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

在 iOS 情况下,Hess 和 Freeman 都表示该对象将被保留。在这一点上,他们之间并不存在矛盾。

仍然强烈建议为所有渠道使用 setter 方法:

资源编程指南,Nib 文件

如果您为 nib 文件定义了出口
对象,你应该总是定义一个
setter 方法(或声明的属性)
用于访问该插座。塞特
网点的方法应保留
他们的价值观...

Case 1) If object isn't retained by anything it will be deallocated upon next autorelease pool drain.

Case 2) In answer you mentioned above Jon Hess has already described (with a reference to documentation) differences between Mac OS X and iOS for this case.

Jon Hess correct or is Freeman correct?

In iOS case both Hess and Freeman say that object will be retained. There is no contradiction between them on this.

It is still highly recommended to have setter methods for all outlets:

Resource Programming Guide, Nib Files

If you define outlets for nib-file
objects, you should always define a
setter method (or declared property)
for accessing that outlet. Setter
methods for outlets should retain
their values...

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文