NSOutlineView/NSTreeController在删除模型对象后没有释放全部对象

3
我有一个非常基本的应用程序:窗口中有一个绑定到NSTreeControllerNSOutlineView。该大纲视图显示一个简单的模型对象(TCCard)。我添加了两个按钮,以便可以从大纲视图中添加和删除模型对象。
通过Instruments(泄漏)查看应用程序,我可以看到当我添加这些对象时,将创建我的模型对象的新实例,但是当我从大纲视图中删除它们时,并没有所有实例都被释放。即使大纲视图没有更多条目,两三个我的模型对象实例仍然保持“活动状态”。
是大纲视图或树控制器在幕后进行缓存吗?请参见以下代码:
#import "TCAppDelegate.h"

#import "TCCard.h"

@implementation TCAppDelegate

- (void)applicationDidFinishLaunching:(NSNotification *)aNotification
{
    TCCard *first = [TCCard new];
    first.title = @"First card";

    // tree controller content is bound to self.cards:
    self.cards = [@[first] mutableCopy]; 
}

- (IBAction)addCard:(id)sender;
{
    TCCard *second = [TCCard new];
    second.title = [NSString stringWithFormat:@"%ld card", self.cards.count];

    [self.treeController addObject:second];
}

- (IBAction)deleteCard:(id)sender;
{
    NSIndexPath *path = [NSIndexPath indexPathWithIndex:self.cards.count - 1];

    [self.treeController setSelectionIndexPath:nil];

    [self.treeController removeObjectAtArrangedObjectIndexPath:path];

    // some model objects continue to live
}

@end

这是一个非常基本的例子。在我的真实应用程序中,这些模型对象相当“重”,具有许多指向其他对象的引用。我真的希望当它们从视图中删除时,所有这些对象都能被释放。
编辑:这个问题甚至可以在苹果的示例代码中重现:https://developer.apple.com/library/mac/#samplecode/DragNDropOutlineView/Introduction/Intro.html#//apple_ref/doc/uid/DTS40008831 在Instruments中运行示例并搜索SimpleNodeData。观察实例数量,然后通过上下文菜单从示例应用程序中删除所有节点。

你正在使用基于视图的大纲视图吗?如果是这样,单元视图会被缓存,如果这些视图与其他对象绑定,则对象可能会意外地保持活动状态。您可以使用委托方法 -outlineView:didRemoveRowView:forRow: 获取行的单元视图,并将其objectValue设置为nil,清除绑定并释放对象。 - user155959
1个回答

0
在方法- (IBAction)addCard:(id)sender中,您使用[TCCard new]分配了一个新的TCCard对象,这将给您一个必须显式释放的对象。因为树控制器会保留您添加的对象,在调用[treeController addObject:]之后,您应该释放它。 就像这样:
- (IBAction)addCard:(id)sender;
{
    TCCard *second = [TCCard new];
    second.title = [NSString stringWithFormat:@"%ld card", self.cards.count];
    [self.treeController addObject:second];
    [second release];
}

提示:在 Xcode 中使用“产品”>“分析”功能,以便在未来检测此类错误。


1
谢谢,但我正在使用ARC,所以释放/自动释放调用是由编译器添加的。 - Mark

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接