如何在垃圾收集的 Obj-C 中保留一个窗口而不持有指向它的指针?

Posted

技术标签:

【中文标题】如何在垃圾收集的 Obj-C 中保留一个窗口而不持有指向它的指针?【英文标题】:How to retain an window without holding a pointer to it in garbage collected Obj-C? 【发布时间】:2010-03-04 19:56:12 【问题描述】:

我目前正在研究 Aaron Hillegaas 著名的“OSX 可可编程”。

在第 12 章中,他希望我使用创建一个 about 窗口

[BOOL] successful = [NSBundle loadNibNamed:@"About" owner:self];

就其本身而言,效果非常好。但是,我正在使用垃圾收集器,并且由于我没有保留指向关于窗口的指针,因此它被垃圾收集,因此在一两秒后消失。如果禁用垃圾收集,它会很好地工作。

有没有办法创建一个窗口而不持有指向它的指针并且不被垃圾收集器吃掉?

【问题讨论】:

在第 12 章中,Aaron Hillegaas 还指出您应该为 About 窗口创建一个 Outlet。如果你这样做,你会保留一个指向窗口的指针,并且它不会被垃圾收集。我忽略了这一点。 【参考方案1】:

您可以使用CFRetain 和retain the window,或使用NSGarbageCollectordisableCollectorForPointer:。但是,您很容易引入内存泄漏。确保用于关闭窗口的任何操作也会释放窗口。

如果传递给关闭操作的sender 继承自NSView,它将有一个window 属性,您可以使用它来获取指向窗口的指针。

然而,这不是 Cocoa 的设计初衷。在 Hillegaas 书中的第 12 章中,他有这样的话:

当第一次发送 showWindow 时,NSWindowController 会自动加载 nib 文件并将窗口移动到屏幕上并移到前面。 nib 文件只加载一次。当用户关闭 [window] 时,它会移出屏幕但不会被释放。下次用户请求 [window] 时,它只是在屏幕上移动。

如果您取消分配“关于”窗口,您的应用将在有人第二次打开它时崩溃或似乎没有响应。

编辑:另一种选择(但不会让您练习加载 nib)是将 About 窗口和 NSWindowController 添加到主 nib(确保取消选中 About 窗口的“启动时可见”属性)。这会使 Main.nib 变得一团糟,但可以完全在 Interface Builder 中完成。连接:

About 控制器的窗口出口到 About 窗口 关于控制器的showWindow: 对关于菜单项的操作 如果您在“关于”窗口中有自己的关闭按钮,请将其连接到窗口的 performClose: 操作。

至于这门课的可取之处,Apple has this to say:

一个非常简单的应用程序可能能够将其所有用户界面组件存储在一个 nib 文件中,但对于大多数应用程序来说,最好将组件分布在多个 nib 文件中。创建较小的 nib 文件可以让您仅加载您立即需要的界面部分。较小的 nib 文件可为您的应用程序带来更好的性能。它们还可以让您更轻松地调试您可能遇到的任何问题,因为查找问题的地方更少。

【讨论】:

当然,如果您不持有指向它的指针,您稍后将如何释放窗口是一个有趣的问题。 (不是说你错了——我只是认为最初的问题可能走错了路。) 那么正确的做法是什么?子类 NSWindowController 用于没有任何交互性的简单 About Window? @Paperflyer:请按照第 12 章进行。 实际上,如果这个窗口应该在应用程序的整个生命周期都存在,那么就没有理由释放它。 谢谢你们,我忽略了书中的一些内容(像往常一样:PEBKAC)。但是你帮助我找到了我的错误并更好地理解了事情!

以上是关于如何在垃圾收集的 Obj-C 中保留一个窗口而不持有指向它的指针?的主要内容,如果未能解决你的问题,请参考以下文章

Haskell或OCML能否处理敏感数据而不通过垃圾收集泄露?

随着时间的推移滑动窗口 - 数据结构和垃圾收集

让我的垃圾收集保留对子小部件的 pyside/Qt 引用作为成员变量会妨碍正确清理吗?

如何在 obj-c 中拖放“.txt”文件

垃圾和悬挂参考有什么区别?

JVM垃圾回收概念