将基于视图的NSOutlineView绑定到Core Data

17

我正在尝试在我的Mac应用程序中将基于视图的OutlineView作为源列表实现。然而,我无法显示值,因此我从Core Data应用程序模板创建了一个小型测试应用程序,并且在其中也无法正常工作。

我在我的数据模型中定义了两个简单的类; 让我们称它们为“Parent”和“Child”。 Parent有一个单一属性“name”,以及一个单一关系“children”。“name”是可选字符串,而children是指向 Child 的可选多对多关系。 Child 具有相同的“name”属性和一个对应于 children 的to-one“parent”关系。我为这两个生成了自定义类,并在 Child 中编写了一个返回nil 的stubbly for children

我从对象库中拖动了一个源列表到我的XIB,并放置了一个树形控制器。 树形控制器的 Children 键路径设置为“children”,它处于实体名称模式下,实体名称为“Parent”,准备内容选中,且其托管对象上下文设置为应用程序委托的上下文。 树形控制器是大纲视图的数据源,我将数据单元格的文本视图绑定到表单视图,使用“objectValue.name”键路径。

-applicationDidFinishLaunching:中,我创建了两个Parent 实例,其中一个带有Child,并分配每个对象的name 属性。

实际问题

No text

现在,完成这些设置后,源列表中出现了行,但是文本字段为空,即使它们被绑定了。 由于我正在使用绑定,并且我相当确定绑定到 objectValue 属性是正确的事情。 发生了什么问题?

如果需要,我可以提供更多细节,但我相当确定这涵盖了我所做的一切。


你解决了这个问题吗?我也遇到了同样的问题,所以我试图复制你的项目。但是我正在使用基于文档的应用程序。我的委托方法从未被调用,并且我的单元格中没有文本值。但是它们确实包含正确的数据。你有可供查看的工作代码吗?非常感激!我可以将我的测试项目上传到Github。 - Mikael
1
你是否将你的视图控制器标记为委托?如果委托方法根本没有被调用,那么你的连接可能是错误的。如果这不能解决你的问题,你应该发布自己的问题。 - Dov
真不敢相信我错过了那个。非常感谢! - Mikael
4个回答

25

哇,就像两周前的我在问这个问题一样。

无论如何,如果你和我一样,问题在于对于基于视图的NSOutlineViews,你需要实现

- (NSView *)outlineView:(NSOutlineView *)outlineView
     viewForTableColumn:(NSTableColumn *)tableColumn
                   item:(id)item;

委托方法并返回你设置的NSTableCellView,否则它们将只给你一个空行。最简单的方法是直接调用:

[outlineView makeViewWithIdentifier:@"MyCell" owner:self]

用你在“标识检查器”中输入的“用户界面项目标识符”,将MyCell替换为任何东西,在NSTableCellView中进行替换。

Objective-C:

- (NSView *)outlineView:(NSOutlineView *)outlineView viewForTableColumn:(NSTableColumn *)tableColumn item:(id)item {
   return [outlineView makeViewWithIdentifier:@"MyCell" owner:self];
}

Swift:

func outlineView(_ outlineView: NSOutlineView, viewFor tableColumn: NSTableColumn?, item: Any) -> NSView? {
    return outlineView.makeView(withIdentifier: NSUserInterfaceItemIdentifier("MyCell"), owner: self)
}

更新于2018年8月2日:

实际上,你不需要设置代理。这是我让它正常工作的方法(经过了与NSTreeController测试,但也应该适用于NSArrayController):

  • 将每个列对象绑定到 arrangedObjects(没有模型关键路径)
  • 将最内层的自定义视图(例如标签字段)绑定到 objectValue.yourCustomValue
  • 这不是必要的,但如果这种方式不起作用,请尝试为列和TableCellView设置标识符,并确保两个标识符相同。对于其余具有不同标识符的列,重复此操作。

截图: 基于视图的NSOutlineView的绑定


6
除了使用绑定之外,您还需要实现这个。 绑定仍然可以处理设置单元格视图的 objectValue,并将单元格视图的子视图绑定到该 objectValue。 但是,为了告诉大纲视图在特定行/列中使用哪个单元格视图,仍然需要使用此方法。 - Boaz Stuller
6
由于数据源列表(Source List)默认情况下使用同一列中的两个不同单元格,即头单元格(HeaderCell)和数据单元格(DataCell),因此必须进行区分。如果只有一个单元格且其标识符设置为自动(Automatic),则可以为您选择其中一个单元格,但这种情况并不适用于数据源列表。 - Dov
谢谢您的回答!我差点放弃搜索了。但是我有以下问题:当我设置标识符时,方法-outlineView:viewForTableColumn:item:从未被调用。当我不设置标识符时,会调用-outlineView:objectValueForTableColumn:byItem:。这里有什么问题吗?我还将部署目标设置为10.7,但没有任何变化:-outlineView:viewForTableColumn:item:没有被调用。 - Paul
哦,很容易解决:当然你需要将你的大纲视图的代理设置为你的自定义数据源。 - Paul
@Dov 很好的回复,你能告诉我这些信息在哪里找到吗?我在苹果的文档中没有找到相关内容。 - Just a coder
@Jai,你指的是哪个信息?在NSTableView文档(其中NSOutlineView是一个子类),文档中的示例代码以及来自2011年问题/答案的WWDC演讲之间:我相信它存在。如果您找到任何相关链接,请添加另一条评论。快速搜索找到了这个由苹果提供的指南:https://developer.apple.com/library/mac/#documentation/cocoa/Conceptual/TableView/PopulatingView-TablesProgrammatically/PopulatingView-TablesProgrammatically.html - Dov

6
如Boaz所述,你需要实现Delegate方法来返回一个视图。
奇怪的是我在文档中找不到这个方法。
关于(id)item参数的类型,它是NSTreeControllerTreeNode,这是NSTreeNode的一个未记录的子类。如果你强制转换它,你可以获得单元格的对象,并根据对象的种类或对象属性来确定单元格视图类型并返回不同的视图。
- (NSView *)outlineView:(NSOutlineView *)outlineView viewForTableColumn:(NSTableColumn *)tableColumn item:(id)item {
    NSTableCellView *view = nil;

    NSTreeNode *node = item;

    if ([node.representedObject isKindOfClass:[Group class]]) {
        view = [outlineView makeViewWithIdentifier:@"HeaderCell" owner:self];
    } else {
        view = [outlineView makeViewWithIdentifier:@"DataCell" owner:self];
    }

    return view;
}

4
这似乎是针对Xcode 4或其后版本的更改。Interface Builder在NSOutlineView下添加了两个NSTableCellView对象。如果您删除NSTableCellView对象,则会返回到一个更加清晰(或至少是有文档说明的)世界,在该世界中,您需要实现以下方法:
outlineView:dataCellForTableColumn:item outlineView:willDisplayCell:forTableColumn:item

...或者至少是当你想要一个源列表时才这样做。无论如何,这就是SourceView示例的设置方式,也是为什么当您尝试重新创建SourceView示例时可能会出现混乱的原因。

或者,如果您想继续使用NSTableCellView对象(它们非常有用),则可以:

  • 将NSOutlineView“Content”绑定到TreeController.arrangedObjects

  • 将NSTextField(和/或NSImageView)绑定到“Table Cell View”,并使用对象值.< key >的模型键路径


1
我创建了一个小的示例项目,它不使用CoreData,但是像@boaz-stuller所说的那样,关键因素是正确选择单元格(类似于iOS中如何处理UITableViewCell)。该项目还填充了一个NSOutlineView
因此,在我的情况下,我已经这样实现了该方法:
- (NSView *)outlineView:(NSOutlineView *)outlineView viewForTableColumn:(NSTableColumn *)tableColumn item:(id)item {

    if ([self isHeader:item]) {
        return [outlineView makeViewWithIdentifier:@"HeaderCell" owner:self];
    } else {
        return [outlineView makeViewWithIdentifier:@"DataCell" owner:self];
    }
}

请在github上查看besi/mac-quickies。大部分内容都是使用IB完成的,或者可以在AppDelegate中找到。

screenshot


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