3

I'm trying to set up a view-based table in Swift using bindings. All of the examples I've seen use a datasource/delegate setup.

I have an array of Flag objects which has two properties - flagName: String and flagImage: NSImage. I have an NSArrayController managing this array.

If I set up a cell-based table, and bind one column to arrangedObjects.flagImage and the other to arrangedObjects.flagName, I get a table displaying images and names, and I can use the array controller's add and remove methods, so there are no problems with my datasource or my array controller.

I have been following the instructions in Apple's TableView Programming Guide to bind my view-based table to my array controller:

  • tableView Content binding: FlagController.arrangedObjects
  • textField Value binding: TableCellView.objectValue.flagName
  • imageView Value binding: TableCellView.objectValue.flagImage

(IBs autocomplete is not happy with the paths for objectValue.flagName respectively flagImage; it doesn't feel that there should be any completion whatsoever and says it can't resolve the path, so it looks as if the problem is with the tableView's content.)

If I do this, my table has a number of rows that corresponds to the number of elements that my array controller is managing at that moment (I have two simple setups, one object vs. 50 objects, so it's clear that something is bound). What I don't get is a display; and selecting a table row does not seem to send back a message to my flagController.

What am I missing? Has anyone been able to make this work? I've had no problems with other bindings in Swift so far, but I'm starting to think that the sudden reappearance of datasource examples is not unrelated to this.

green_knight
  • 1,319
  • 14
  • 26

1 Answers1

2

It sounds like you've failed to implement the delegate method -tableView:viewForTableColumn:row:. That's a common cause of blank tables.

You don't actually have to implement that if you make sure the identifier of the table column and the identifier of the table cell view are the same in IB.

Otherwise, the method can just do this:

- (NSView*) tableView:(NSTableView*)tableView viewForTableColumn:(NSTableColumn*)tableColumn row:(NSInteger)row
{
    return [tableView makeViewWithIdentifier:@"TheIdentifierOfYourTableCellView" owner:self];
}

(It could also do more, if desired.)

Ken Thomases
  • 88,520
  • 7
  • 116
  • 154
  • Is the delegate method necessary for view-based tables? My understanding was that you could set them up entirely with bindings, just as you can cell-based tables; this sounds as if it would blend the two approaches. – green_knight Aug 08 '14 at 22:08
  • As mentioned in my second paragraph, it's not necessary to implement the delegate method, but bindings has nothing to do with it. You have to give the table view a way to find the table cell view. That's done either by the delegate method or by making the table cell view have the same identifier as the table column. That can be set up in IB or it can be done by calling `-[NSTableView registerNib:forIdentifier:]`. – Ken Thomases Aug 09 '14 at 03:36
  • Thank you for your patience; for some reason I failed to parse it first time around :-( Out of interest - how could I have found this out? I looked at the documentation again, and found no mentioning of this. – green_knight Aug 09 '14 at 08:50
  • Unfortunately, it's a bit spread out. Some of it is in the various table-view-related class references. Some of it is in the AppKit release notes covering the releases since 10.7, when view-based tables were introduced. Some of its is in the NSTableView.h header file. – Ken Thomases Aug 09 '14 at 11:37