我想将NSTableView
或NSCollectionView
绑定到由NSArrayController
或NSArray
属性组成的数据源。但是,我希望在代码中执行此操作,因为出于各种技术原因,我的UI中没有XIB。
由于Apple没有提供任何关于如何操作的文档,我正在寻找一个规范的答案,很好地表达了应该如何做到这一点。
如果答案是在Objective-C或Swift中,则无关紧要。
以下是不起作用:
contactsTableView.bind(NSContentBinding,
toObject: myViewModel,
withKeyPath: "contacts",
options: nil)
“contacts”是NSArrayController或带有字符串的NSArray。
答案 0 :(得分:3)
您需要绑定到NSArrayController
,而不仅仅是NSArray
,因为您几乎肯定希望将通过数组元素绑定到其属性和NSArray
不支持。绑定建立在Key-Value Observing之上,您无法通过数组或集合进行键值观察。
此外,阵列控制器通常是模型 - 视图 - 控制器中控制器层的一部分。因此,"联系"是不合理的。可以是命名myViewModel
属性的关键路径,也可以是数组控制器。它应该是视图或窗口控制器的属性。
如果您的表视图基于NSCell
,则通常应该绑定表列而不是表视图本身。表视图将根据其列的绑定自动绑定一些自己的绑定。如果要禁用该自动行为,则只能显式绑定表视图的绑定。
所以,你可以为每一栏做到:
[tableColumn bind:NSValueBinding toObject:self.contactsArrayController withKeyPath:@"arrangedObjects.propertyAppropriateToColumn" options:nil];
如果您的表视图是基于视图的,则应该绑定表视图的绑定而不是列。所以,你会这样做:
[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:
中的拆分,但那些不直接为您提供单元格视图。您需要自己将行视图中的单元格视图与表格列相关联。 (不难,只是单调乏味。)
如果表格单元格视图是响应-setObjectValue:
的控件或其他视图,则表视图将调用该视图以将对象值设置为数组的元素。在这种情况下,您可能希望更改内容绑定以将通过 arrangedObjects
转到数组元素的相关属性。
集合视图的情况类似于基于视图的表视图。您只能绑定NSContentBinding
和NSSelectionIndexesBinding
;没有NSSortDescriptorsBinding
,因为集合视图没有用户更改排序的界面(如表格列标题)。集合视图将每个集合视图项representedObject
设置为数组的元素。项目视图或其子视图应通过representedObject
绑定到项目,并绑定到元素的某个特定属性。
如果您没有使用NIB,那么您可能希望使用NSCollectionViewItem
的自定义子类。这将在调用super之后在其-viewDidLoad
方法(10.10或更高版本)或其-loadView
方法中设置绑定。您可以在解除分配时拆除绑定。或者,您可以设置它们并在-viewWillAppear
和-viewWillDisappear
中将其拆除。