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

标签 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) 的情况,显然您必须显式释放。如果不这样做,它会在 View 消失后继续存在。没问题。

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

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

查看著名的引用链接:https://developer.apple.com/library/archive/documentation/Cocoa/Conceptual/LoadingResources/CocoaNibs/CocoaNibs.html这是非常可疑的:

"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!]"

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

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

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

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

他们在说什么?

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

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

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

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

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

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

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

<小时/>

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

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

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

所以,这就是答案。

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

最佳答案

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

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.

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: ),否则期望对象所有权被管理为多于。

<小时/>

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.

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

<小时/>

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.

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

关于iphone - 如果您有 IBOutlet,但没有属性,那么它是否保留?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/5523290/

相关文章:

.net - 静态类/成员在哪里分配?

C++动态加载类: Why is a "destroy" function needed?

wpf - 使用 MVVM 的 DataTemplate 驱动的 View 注入(inject)

iphone - 请求发送获取错误 : [CFString release]: message sent to deallocated instance 0x6a83e00

iphone - 所以 "lame"- 如何从 float = 0.39824702 只是 float = 0.398?

uitableview - 将 scrollViewWillEndDragging 中的 targetContentOffset 更新为错误方向的值不会产生动画

iphone - 如何在 Objective c 中为 iphone 创建一个字符串数组

iphone - 模型更改时更新 UI

iphone - UITextView 自动完成不是我订单的文本

objective-c - 没有从 Core Data 获取数据