objective-c - 调用 makeViewWithIdentifier :owner: causes ARC to re-create ivar

标签 objective-c automatic-ref-counting nstableview

我正在编写一个沙盒 ARC 应用程序,其中包含基于 View 的 NSTableView,它接受拖放文件 (NSURL)。我在以下 NSTableViewDelegate 方法中遇到了一些明显的奇怪之处:<​​/p>

- (NSView *)tableView:(NSTableView *)tv
   viewForTableColumn:(NSTableColumn *)tc
                  row:(NSInteger)row
{
    // `files' is an NSMutableArray* ivar containing NSURLs
    // that have been dropped into this table
    NSURL *url = [files objectAtIndex:row];
    NSString *fileName = [url lastPathComponent];
    NSImage *icon = [self iconForURL:url];

    NSTableCellView *view = [tv makeViewWithIdentifier:[tc identifier] owner:self];
    [[view textField] setStringValue:fileName];
    [[view imageView] setImage:icon];

    return view;
}

我可以将一个文件拖到 TableView 中,它会正确显示。当我拖动第二个文件时,出现此错误:

*** Canceling drag because exception 'NSRangeException' (reason '*** -[__NSArrayM insertObject:atIndex:]: index 1 beyond bounds for empty array') was raised during a dragging session

通过调试器,我发现在调用 makeViewWithIdentifier:owner: 之后,files“变空”——实际上变成了一个新的对象实例。我认为这是我不理解的 ARC 的某些方面,但在我看来,该对象对其自己的 ivar 有很强的引用(默认情况下);它怎么可能从我的手下被释放并重新创建?

我想出了两个技巧来解决这个问题:

  1. 将 ivar 作为表格单元格 View 的所有者传递(希望在未来的版本中它将继续保持强引用);或
  2. 创建一个局部变量来指向 ivar 的对象,并将 ivar 重新分配给旧对象(这显然是浪费,因为它同时创建了一个替换数组)。

我在这里缺少什么?这些解决方法应该不是必需的。

最佳答案

调用 -makeViewWithIdentifier:owner: 将导致将 -awakeFromNib 消息发送给所有者。这是有记录的,但仅在头文件中(编辑:主文档已更新以引用此内容)。

我想您的文件数组只是在 -awakeFromNib 中重新初始化。

给定情况下的解决方案(加载 View 原型(prototype)而不是 Nib )只是将 nil 作为所有者传递。加载已注册 nib 的其他实现(请参阅 -registerNib:forIdentifier:)可能需要一个所有者,该所有者可能是委托(delegate)(或不是)。因此,可能必须检测和捕获对 -awakeFromNib 的多次调用。设置一个属性来标记 Nib 加载并且只执行一次所需的初始化是很简单的。

请注意,此方法的 Apple 文档已更新以反射(reflect)这一点:

Note that awakeFromNib is called each time this method is called, which means that awakeFromNib is also called on owner, even though the owner is already awake.

关于objective-c - 调用 makeViewWithIdentifier :owner: causes ARC to re-create ivar,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13556165/

相关文章:

ios - __ block 的弱通用变量声明

swift - 将 [unowned self] 添加到闭包参数 Swift

ios - __bridge 不需要方法参数?

swift - NSTable中对象的列向数据

swift - 准确获取 NSTextField 包装大小 (Swift)

objective-c - 包含点 : for UIBezierPath crashes

iOS 图表 - 如何以编程方式初始化 LineChartView

cocoa - 对带有核心数据存储的 NSTableView 的拖放支持

objective-c - TouchesMoved 仅返回已更改的触摸,忽略未更改的触摸

objective-c - 我收到一条错误消息,内容为 "Use of Undeclared Identifier ' 事件'”