0

我正在尝试实现我自己的 NSViewController 版本(为了向后兼容),但我遇到了绑定问题:由于绑定保留了它们的目标,所以每当我通过 File 的所有者绑定时,我都有一个保留圈。

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

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

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

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

如果您在 release/retain/autorelease 覆盖处设置断点,您会看到 _NSBindingInfo 保留了 TestNibOwner,但在泄漏的情况下从不释放它。

有人知道怎么修这个东西吗?

4

3 回答 3

2

与 class-dump 和朋友一起进行了一些调查,看起来 Apple 有一个名为 NSAutounbinder 的私有类,它负责为 NSViewController 和 NSWindowController 等类处理这项肮脏的工作。无法真正说出它是如何工作的或如何复制它。

所以,我不能真正回答你关于如何防止在加载的 nib 中的任意绑定发生保留周期的问题,但也许知道苹果在作弊是一种安慰,而且你没有遗漏任何明显的东西。:-)

于 2010-01-17T16:40:00.560 回答
1

我为同样的问题做的一件事是在我的笔尖内创建一个代理 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
于 2010-01-17T19:04:17.873 回答
0

当你从它的超级视图中删除你的视图时,你是否也在向它发送另一个 -release 消息?它是通过从笔尖取消归档创建的,对吗?

于 2010-01-17T13:55:13.603 回答