【问题标题】:NSOutlineView/NSTreeController not releasing all model objects after removing themNSOutlineView/NSTreeController 删除后没有释放所有模型对象
【发布时间】:2013-04-16 07:58:57
【问题描述】:

我有一个非常基本的应用程序:一个带有NSOutlineView 绑定到NSTreeController 的窗口。大纲视图显示一个简单的模型对象 (TCCard)。我添加了两个按钮,以便可以在大纲视图中添加和删除模型对象。

查看 Instruments (Leaks) 中的应用程序,我可以看到我的模型对象的新实例是在我添加它们时创建的,但在我从大纲视图中删除它们时并不是所有实例都被释放。即使大纲视图没有更多条目,我的模型对象的两个或三个实例也始终保持“活动”状态。

大纲视图或树控制器是否在幕后进行一些缓存?代码如下:

#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

这是一个非常基本的例子。在我的真实应用程序中,这些模型对象非常“沉重”,并有很多对其他对象的引用。我真的希望它们从视图中移除时全部释放。

编辑:即使使用 Apple 的示例代码也可以重现此问题:https://developer.apple.com/library/mac/#samplecode/DragNDropOutlineView/Introduction/Intro.html#//apple_ref/doc/uid/DTS40008831

在 Instruments 中的示例中运行并搜索 SimpleNodeData。观察实例数量,然后从示例应用程序中删除所有节点(通过上下文菜单)。

【问题讨论】:

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

标签: cocoa nsoutlineview nstreecontroller retain-cycle


【解决方案1】:

- (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 中使用 Product > Analyze 以在将来检测此类错误。

【讨论】:

  • 谢谢,但我使用的是 ARC,所以编译器会添加 release/autorelease 调用。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-10-29
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多