NSViewController 如何避免绑定内存泄漏? [有示例应用程序]

发布于 2024-08-17 18:47:43 字数 618 浏览 3 评论 0原文

我正在尝试实现我自己的 NSViewController 版本(为了向后兼容),并且我遇到了绑定问题:由于绑定保留其目标,因此每当我通过文件所有者绑定时,我都会有一个保留圈。

所以我想我只是明确地从其超级视图中删除我的视图并释放顶级对象,这将处理绑定,因为我的控制器不再保留视图,所以他们释放了我,我可以离开。但由于某种原因,我的视图控制器仍然没有被释放。以下是展示该问题的示例应用程序:

http://dl.dropbox.com/u/ 34351/BindingsLeak.zip

构建它,启动它,然后点击 Cmd-K(“编辑”菜单中的“创建 Nib”)将 NIB 加载到空窗口中。再次按下 Cmd-K 以释放第一个视图控制器 (TestNibOwner) 并加载一个新的视图控制器。不过,旧的视图控制器永远不会被释放。

删除复选框上的“值”绑定,它就可以正常释放了。

如果您在释放/保留/自动释放覆盖处设置断点,您会看到 _NSBindingInfo 保留 TestNibOwner,但在泄漏情况下永远不会释放它。

有人知道如何解决这个问题吗?

I'm trying to implement my own version of NSViewController (for backwards compatibility), and I've hit a problem with bindings: Since bindings retain their target, I have a retain circle whenever I bind through File's owner.

So I thought I'd just explicitly remove my view from its superview and release the top level objects, and that would take care of the bindings, because my controller isn't holding on to the views anymore, so they release me and I can go away. But for some reason, my view controller still doesn't get released. Here's a sample app exhibiting the problem:

http://dl.dropbox.com/u/34351/BindingsLeak.zip

Build it, launch it, and hit Cmd-K ("Create Nib" in "Edit" menu) to load a NIB into the empty window. Hit Cmd-K again to release the first view controller (TestNibOwner) and load a new one. The old view controller never gets dealloced, though.

Remove the "value" binding on the checkbox, and it gets released just fine.

If you set breakpoints at the release/retain/autorelease overrides, you see that _NSBindingInfo retains the TestNibOwner, but never releases it in the leaking case.

Anyone know how to fix this?

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

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

发布评论

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

评论(3

淡淡绿茶香 2024-08-24 18:47:44

当您从其超级视图中删除视图时,您是否还会向其发送另一条 -release 消息?它是通过从笔尖取消存档创建的,对吧?

When you remove your view from its superview, are you also sending it another -release message? It was created by unarchiving from the nib, right?

君勿笑 2024-08-24 18:47:43

通过类转储和朋友进行了一些调查,看起来苹果有一个名为 NSAutounbinder 的私有类,它负责处理 NSViewController 和 NSWindowController 等类的脏工作。但无法真正说出它是如何工作的或如何复制它。

所以,我无法真正回答你关于如何防止加载笔尖中的任意绑定发生保留周期的问题,但也许知道苹果在作弊是一些安慰,并且你没有错过任何明显的东西。 :-)

Doing a little investigation with class-dump and friends, it looks like Apple has a private class called NSAutounbinder that takes care of this dirty work for classes such as NSViewController and NSWindowController. Can't really tell how it works or how to replicate it though.

So, I can't really answer your question on how to prevent the retain cycle from happening for arbitrary bindings in a loaded nib, but perhaps it's some consolation to know that Apple is cheating, and you're not missing anything obvious. :-)

时光倒影 2024-08-24 18:47:43

我针对同样的问题所做的一件事是在我的笔尖内创建一个代理 NSObjectController 。我的类似 NSViewController 的类有一个指向该代理的指针,并且所有绑定都通过它绑定。当我想清理视图控制器时,我在对象控制器上执行 [selfProxy setContent:nil] 并释放视图控制器。在这种情况下,NSObjectController 代理充当自动解除绑定器。

它更加手动,你不能自己释放视图,但它确实解决了保留问题。

我建议你这样做:

-(void) releaseTopLevelObjects
{
    // Unbind the object controller's content by setting it to nil.
    [selfProxy setContent:nil];

    NSLog( @"topLevelObjects = %@", topLevelObjects );
    [topLevelObjects release];
    topLevelObjects = nil;
}

在你的笔尖中,绑定将通过如下路径发生:

selfProxy.content.representedObject.fooValue

One thing I've done for the same problem is to create a proxy NSObjectController inside my nib. My NSViewController-like class has a pointer to this proxy and all bindings are bound through it. When I want to cleanup the view controller, I then do [selfProxy setContent:nil] on the object controller and release the view controller. In this instance the NSObjectController proxy acts as the auto-unbinder in this case.

It's more manual and you can't just release the view by itself, but it does solve the retain problem.

I'd suggest you do this:

-(void) releaseTopLevelObjects
{
    // Unbind the object controller's content by setting it to nil.
    [selfProxy setContent:nil];

    NSLog( @"topLevelObjects = %@", topLevelObjects );
    [topLevelObjects release];
    topLevelObjects = nil;
}

In your nib, bindings would happen through a path like:

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