(reposted because of an apparent bounce)

On Aug 2, 2012, at 22:16 , Erik Stainsby <[email protected]> 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! 

I don't know that you have a problem with bindings as such. I think your 
problems are mainly with NSArrayController. On top of that, I think you might 
have some terminology wrong (possibly just typos).

> So tonight I have an NSArrayController (RSTableArrayController)

Ugh, subclassing an array controller (any NSController, really) is going to 
make you unhappy, eventually.

> 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]]];

Ugh, again, sorry to say. There are several warning flags here.

-- It's rarely easier to use a NSDictionary instead of define a custom class. A 
dictionary is a better solution only when the data objects have properties that 
cannot be determined until run time. If you know the properties of your data, 
step up and write the custom class right from the beginning. It'll be easier to 
write your code, and easier to debug.

-- By doing something like the above in an array controller subclass, you've 
muddied your MVC design pattern. The array of dictionaries *is* your data model 
-- or perhaps is just part of the data model -- but exposing its internal 
structural details, here in a mediating controller, is about 2 controllers away 
from where your data model really should be.

-- This code is not KVO compliant. This may not matter initially, if it happens 
before the view gets displayed, but it suggests you're going to think of your 
data (self.content) as an array, rather than as an indexed property of a data 
model object, and I'll bet you run into KVO compliance problems later.

> 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).
> 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- [%04d] %@: %@", __PRETTY_FUNCTION__, __LINE__, 
> identifier,[dict valueForKey:identifier]);
>       return [dict valueForKey:identifier];
> }
> 
> 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. 

The data source code seems fine (though I didn't peer at it line by line), but 
I think it's in the wrong place. The more usual placement in a window 
controller is better than putting it in the array controller. The less code 
references you have to the array controller, the easier your app will be write 
and debug. (Best of all: don't even define an outlet to the array controller. 
Unfortunately, that's not always feasible, but I believe it's always desirable.)

> 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

Do you mean "Table View Cell"? These days, "Table Cell View" means something 
quite different.

>                               » Static Text
>                                Text Field Cell

I'm not sure where these levels come from. In IB, the next level down from 
"Table Column" is some kind of cell, and there's nothing else. Did you perhaps 
create a view-based table instead of a cell-based table? Did you really want a 
view-based table (in which case you're implementing the wrong data source 
methods)?

> Given that the delegate method is called  -[tableView: 
> objectValueForTableColumn: row:]  I should expect to bind the 
> arrayController's objectValue

I'm not sure what you mean here. Array controllers don't have an "objectValue" 
property or binding. Array controller bindings have names like "contentObject" 
or "contentArray".

> in the Bindings Inspector to the ?node?  in the object browser.

The normal thing is to bind the table column's "value" binding to the array 
controller's "arrangedObjects" controller key, specifying the model key that 
represents the property you want to display -- "label" in this case.

You *can* bind properties of the cell itself, but since certain properties 
bound from the table column are propagated *down* to the cell (when the cell 
for the column is requested) and certain cell properties are overridden (when 
the cell is prepared for use in a particular row/column context), things you do 
to the cell may get overridden.



_______________________________________________

Cocoa-dev mailing list ([email protected])

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:
https://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com

This email sent to [email protected]

Reply via email to