使用没有XIB的Cocoa Bindings填充NSTableView或NSCollectionView [英] Populating a NSTableView or NSCollectionView using Cocoa Bindings without XIBs

查看:583
本文介绍了使用没有XIB的Cocoa Bindings填充NSTableView或NSCollectionView的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想将 NSTableView NSCollectionView 绑定到由 NSArrayController NSArray 属性。但是,我希望在代码中这样做,因为我的用户界面中没有XIBs因为各种技术原因。

I would like to bind my NSTableView or NSCollectionView to a datasource consisting of a NSArrayController or NSArray property. However, I wish to do this in code, as I have no XIBs in my UI for various technical reasons.

由于苹果没有提供任何文档如何做,我正在寻找一个规范的答案,给出一个良好的表示,如何这是应该做的。

As Apple does not provide any documentation on how to do so, I'm looking for a canonical answer, giving a good representation on how this is supposed to be done.

如果回答是在Objective-C或Swift中,这并不重要。

It doesn't matter if the answer is in Objective-C or Swift.

>不起作用::

Here's what doesn't work:

contactsTableView.bind(NSContentBinding,
    toObject: myViewModel,
    withKeyPath: "contacts",
    options: nil)

NSArrayController或NSArray与字符串。

With "contacts" being either a NSArrayController or NSArray with strings in.

推荐答案

您需要绑定到 NSArrayController ,而不只是一个 NSArray ,因为你几乎肯定想要通过数组元素绑定到它们的属性和 NSArray 不支持。绑定是建立在键值观察之上的,你不能通过数组或集合观察键值。

You need to bind to an NSArrayController, not just an NSArray because you almost certainly want to bind through the array elements to their properties and NSArray does not support that. Bindings is built on top of Key-Value Observing and you can't key-value observe through arrays or sets.

此外,数组控制器通常是控制器的一部分模型 - 视图 - 控制器中的层。因此,contacts可能是命名 myViewModel 的属性的关键路径并且也是一个数组控制器是没有意义的。它应该是视图或窗口控制器的属性。

Also, an array controller is usually part of the controller layer in Model-View-Controller. So, it doesn't make sense that "contacts" could be a key path naming a property of myViewModel and also be an array controller. It should be a property of the view or window controller.

如果您的表视图是 NSCell 应该通常绑定表列,而不是表视图本身。表视图将基于其列的绑定自动绑定几个自己的绑定。

If your table view is NSCell-based, you should usually bind the table columns rather than the table view itself. The table view will automatically bind a few of its own bindings based on the bindings of its columns. You would only explicitly bind the table view's bindings if you want to disable that automatic behavior.

因此,您可以为每一列设置:

So, you might do, for each column:

[tableColumn bind:NSValueBinding toObject:self.contactsArrayController withKeyPath:@"arrangedObjects.propertyAppropriateToColumn" options:nil];

如果您的表视图是基于视图的,您应该绑定表视图的绑定,而不是列。所以,你会做:

If your table view is view-based, you should bind the table view's bindings and not the columns. So, you would do:

[contactsTableView bind:NSContentBinding toObject:self.contactsArrayController withKeyPath:@"arrangedObjects" options:nil];
[contactsTableView bind:NSSelectionIndexesBinding toObject:self.contactsArrayController withKeyPath:@"selectionIndexes" options:nil];
[contactsTableView bind:NSSortDescriptorsBinding toObject:self.contactsArrayController withKeyPath:@"sortDescriptors" options:nil];

如果您的表格单元格视图 NSTableCellView 一个子类,然后表视图将其 objectValue 属性设置为数组中的相应元素。 NSTableCellView 中的视图应该使用 objectValue.propertyAppropriateToThatView 键路径绑定到它。如果不使用NIB,则必须在 -tableView:viewForTableColumn:row:委托方法中设置此绑定。你还必须拆除绑定,这将是一种困难,因为表视图不告诉你,当它丢弃单元格视图。它可能工作在 -tableView:didAddRowView:forRow:中进行设置,并在中清除-tableView:didRemoveRowView:forRow:,但那些不直接给你单元格视图。您需要将行视图中的单元格视图与表列相关联。 (不难,只是繁琐。)

If your table cell view is NSTableCellView or a subclass, then the table view will set its objectValue property to the corresponding element from the array. The views within the NSTableCellView should bind to it, using a key path like objectValue.propertyAppropriateToThatView. If you're not using NIBs, you're going to have to set up this binding in your -tableView:viewForTableColumn:row: delegate method. You also have to tear down the bindings, which is going to be kind of hard because the table view doesn't tell you when it discards a cell view. It might work to do the setup in -tableView:didAddRowView:forRow: and teardown in -tableView:didRemoveRowView:forRow:, but those don't directly give you the cell views. You'll need to correlate the cell views within the row view to the table columns yourself. (Not hard, just tedious.)

如果您的表格单元格视图是一个控件或其他视图,响应 -setObjectValue:,那么表视图将调用它来将对象值设置为数组的元素。在这种情况下,您可能要将内容绑定更改为通过 arrangeObjects 到数组元素的相关属性。

If your table cell view is a control or other view which responds to -setObjectValue:, then the table view will call that to set the object value to the element of the array. In that case, you may want to change the content binding to go through arrangedObjects to the relevant property of array elements.

集合视图的情况类似于基于视图的表视图。您只能绑定 NSContentBinding NSSelectionIndexesBinding ;没有 NSSortDescriptorsBinding ,因为集合视图没有为用户更改排序的接口(如表列标题)。集合视图将每个集合视图项的resentObject 设置为数组的元素。项目视图或其子视图应通过resentObject 绑定到该元素的某个特定属性。

The situation with a collection view is similar to a view-based table view. You'd only bind NSContentBinding and NSSelectionIndexesBinding; there's no NSSortDescriptorsBinding because collection view's don't have an interface for the user to change the sorting (like table column headers). The collection view will set each collection view item's representedObject to the element of the array. The item view or its subviews should bind to the item, through representedObject to some specific property of the element.

如果你不使用NIB,你可能想使用 NSCollectionViewItem 的自定义子类。这将在其 -viewDidLoad 方法(10.10或更高版本)或其 -loadView 方法中设置绑定到超级。当释放绑定时,可以拆除绑定。或者,您可以设置它们,并在 -viewWillAppear -viewWillDisappear 中将其删除。

If you aren't using NIBs, you'll probably want to use a custom subclass of NSCollectionViewItem. That will set up the bindings in its -viewDidLoad method (10.10 or later) or its -loadView method after calling through to super. You can tear down the bindings when it deallocates. Alternatively, you can set them up and tear them down in -viewWillAppear and -viewWillDisappear.

这篇关于使用没有XIB的Cocoa Bindings填充NSTableView或NSCollectionView的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆