Re: Very basic table binding blind spot
Re: Very basic table binding blind spot
- Subject: Re: Very basic table binding blind spot
- From: Kyle Sluder <email@hidden>
- Date: Fri, 03 Aug 2012 00:11:24 -0700
On Aug 2, 2012, at 10:16 PM, Erik Stainsby <email@hidden> wrote:
>
>
> I do so wish there was a Complete Idiot's Guide to Cocoa Table Bindings … The very flexibility which I know must be their great virtue tends to obscure the clear path from my sight more often than not. Forest, trees, trees, forest … Oh! Something shiny!
Bindings are an 80% solution—that is, they usually get you 80% of the way there and then you have to throw them out and start over with the data source based approach. :)
>
> So tonight I have an NSArrayController (RSTableArrayController) which I have populated with dictionary objects of the form:
>
> [self.content addObject:[NSDictionary dictionaryWithObjects: [NSArray arrayWithObjects: key, [mvo valueForKey:key],nil] forKeys:[NSArray arrayWithObjects:@"label",@"value",nil]]];
>
>
>
> For this simple two column data I have a two column table, using Table View Cells (I'm going to have visual objects in place of the 'label' later on).
You should consider using a view-based table view if you're targeting 10.7 or later. They're so much nicer!
> I have set the identifier for the tableView columns very imaginatively to "label", and "value".
> The array controller is also < NSTableViewDataSource, NSTableViewDelegate >. I have implemented the following two delegate methods:
>
> - (NSInteger) numberOfRowsInTableView:(NSTableView *)aTableView {
> return self.content.count;
> }
>
> - (id) tableView:(NSTableView *)aTableView objectValueForTableColumn:(NSTableColumn *)tableColumn row:(NSInteger)rowIndex {
> NSString * identifier = [tableColumn identifier];
> NSDictionary * dict = [self.content objectAtIndex:rowIndex];
> NSLog(@"%s- [d] %@: %@", __PRETTY_FUNCTION__, __LINE__, identifier,[dict valueForKey:identifier]);
> return [dict valueForKey:identifier];
> }
The whole point of bindings is that you don't implement these two methods. They're data source methods, not delegate methods, and their functionality is completely supplanted by bindings.
>
> In the nib, I have an ArrayController object of the class described above RSTableArrayController. It is wired up as the delegate and dataSource for the tableView.
>
>
> And here is where I get lost time and again, tracing the appropriate path to the content and it's constituent data parts and binding them to the appropriate element in the tableView.
>
> » Scroll View
> » Table View
> » Table Column
> » Table Cell View
> » Static Text
> Text Field Cell
If you want to use bindings, first delete your implementations of the above methods.
Then, how you proceed depends on whether you're using a view-based table view.
For a cell-based table view: bind all of your table columns' Content bindings to the arrangedObjects key of your controller. Then bind the Value binding of the text field cell in each column to the appropriate keypath of your controller's arrangedObjects. So the text field cell in the label column will be bound to your controller object with a controller key of arrangedObjects and a model keypath of "label". Similarly for the value column.
If the Content bindings of a cell-based table view are all bound to the same keypath of the same controller, the cell-based table view automatically binds its Content binding to the same keypath of the same controller. You don't need to set this binding up yourself, but it's good to know what it's for.
View based table view bindings make a lot more sense. You bind the table view's Content binding to the arrangedObjects of your array controller (just once, rather than once per column). Then you bind each of the views inside each column's NSTableCellView to the appropriate keypath of their enclosing NSTableCellView's objectValue property.
For both view-based and cell-based table views, if the table view's content binding is set (whether explicitly or automatically) the table view automatically binds its selectionIndexes and sortDescriptors bindings to the appropriate keys of the controller its Content binding is bound to.
To recap, for cell-based table views:
[LabelColumn].content => [ArrayController].arrangedObjects
[LabelColumn.cell].value => [ArrayController].arrangedObjects.label
[ValueColumn].content => [ArrayController].arrangedObjects
[ValueColumn.cell] => [ArrayController].arrangedObjects.value
For view-based table views:
[Table View].content => [ArrayController].arrangedObjects
[LabelColumnCellView.textField].value => [LabelColumnCellView].objectValue.label
[ValueColumnCellView.textField].value => [ValueColumnCellView].objectValue.value
View-based table views have the advantage that even if you decide to revert to standard NSTableDataSource methods for providing the data to your table view, you can still use bindings *within* your NSTableCellViews to provide the data to your text fields.
--Kyle Sluder
_______________________________________________
Cocoa-dev mailing list (email@hidden)
Please do not post admin requests or moderator comments to the list.
Contact the moderators at cocoa-dev-admins(at)lists.apple.com
Help/Unsubscribe/Update your Subscription:
This email sent to email@hidden