On Jun 4, 2008, at 12:05 AM, Daniel Child wrote:

I worked out a super basic bindings case where table columns display the ivars of a Word class via bindings. Words have three ivars with standard accessors. An ArrayController manages a table of these words

Hmm. An NSArrayController doesn't manage tables, it manages an array (as its name implies). So, do you have an array somewhere with instances of the Word class? Where is it? For example, is it a property of File's Owner, with a key "words"?

, with appropriate bindings between the columns and ivars. It works as expected. So far so good.

Now, however, I want to bind the same table to an intervening class, WordList, which contains an array of Words.

Contains how? What is the interface of this WordList class? What properties does it have?


I tried setting the ArrayController's class to WordList, and bound the value of individual table columns to ArrayController.arrangedObjects.wordList.<Word ivar>. (wordList is the mutable array in the WordList class.)

That doesn't seem right. The Class Name should indicate what kind of elements are in the array being managed. That's still Word, unless I'm misunderstanding what you're trying to achieve.

Similarly, the Content Array binding of the NSArrayController should refer to the array of Words maintained by the WordList instance (perhaps as a key path from the File's Owner, or whatever). Therefore, it doesn't make sense to have ".arrangedObjects.wordList" appear in the key path of the table column bindings. The arrangedObjects are already the words in the WordList instance.

Let's suppose that File's Owner has a property "wordList" that is a to- one relationship to a WordList instance. Let's also suppose that the WordList class has a property "words" which is the to-many relationship to some instances of Word. Then, the NSArrayController's Content Array binding should be bound to File's Owner with Model Key Path "wordList.words". That is, this array controller is managing access to the words of the wordList of File's Owner. Now, the table columns would be bound to the NSArrayController, with the Controller Key "arrangedObjects" and Model Key Path being whichever property of an individual Word instance should be presented in the column. Note that the table column bindings are pretty much unchanged from the case without the WordList class. This is a reflection of the encapsulation provided by the MVC design pattern and KVC/KVO/bindings. If the model changes -- in this case, the array of words moving from being a direct property of File's Owner to being a property of a WordList object held by the File's Owner -- the controller which mediates between the view and the model may have to changed, but the view itself need not.



That didn't work. It appears I can add and remove lines to the table, but the values I type in do not display after I tab out to the next column.

It's hard to know for sure what's going on without knowing the details of the WordList class. I suspect, from what you described, that the columns were trying to map to WordList objects, but that they had no idea how to convert what you type (a string) into a WordList.


More importantly, could someone clarify the rhyme and reason for choosing when to:

- binding the content arrangedObjects           versus
- binding the value (of table cells) to arrangedObjects.<ivar>            versus
- binding the contentArray to selection.<ivars?>

Apple's Figure 13 of Cocoa Bindings Programming Topics takes a huge leap from the trivial case of two simple controls (slider and textfield) to a maze of connections between and among columns and controllers. I simply don't see when to choose among the various options, or what they stand for.

In many cases, there's only one binding to make. For example, a table column has a Value binding, but not a Content or Content Array binding.

For an NSArrayController, there are Content Array, Content Array For Multiple Selection, Content Object, and Content Set bindings, which can be confusing. You'll need to look in the Cocoa Bindings Reference for the page on the NSArrayController bindings. The most common case is to bind Content Array.

An NSPopUpButton also has a variety of content bindings. Again, check the page for NSPopUpButton in the Cocoa Bindings Reference. In this case, it's useful to do a full-text search for the combined keywords "contentObject contentValues" (without the quotes) to find some additional documentation. In particular, the 10.4 AppKit release notes (of all places) have important guidelines on using those bindings. They say:

Selection widgets (NSPopUpButton/NSPopUpButtonCell and NSMatrix) now offer a contentObjects binding in addition to the content and contentValues bindings (the contentObjects binding becomes available only if content is bound). This allows you to bind the content of the widget to an array (content binding), the displayed values to a dependent array (contentValues binding - which needs to use a key path that is an extension to the one of the content binding), and the "represented" objects to be handled through the selectedObject/ selectedObjects bindings to another depdendent array (contentObjects - which also needs to use a key path that is an extension to the one of the content binding). For example, if you have an array with dictionaries (that can be bound to a controller through the "selection.dictionaries" key) which each have values for a key "displayName" and a key "representedObject", you can bind content of a pop-up button to "selection.dictionaries", contentValues to "selection.dictionaries.displayName" and contentObjects to "selection.dictionaries.representedObject" - the selectedObject will then operate on the "representedObject" values, while the pop-up displays the "displayName" values in the user interface. Of course, if you do not use the contentObjects binding, the represented objects are still the values in the array to which content is bound.



Now, as to the question of what to bind to (arrangedObjects, arrangedObjects.key, selection.key, etc.), that depends on what you're trying to accomplish. If you want to access all of the objects in the array being managed by an array controller, you bind to that controller's "arrangedObjects" controller key. If you want to access a particular property of the objects in that array, you specify a model key path to that property. If you don't want all of the objects but just those that are selected, you bind to the "selection" controller key of the controller which is tracking that selection. And, again, if you want to access a specific property of the selected object(s), you specify a model key path as well. There are also the selectionIndexes, selectionIndex, and selectedObjects keys. See <http://developer.apple.com/documentation/Cocoa/Conceptual/CocoaBindings/Concepts/CntrlSelection.html#//apple_ref/doc/uid/TP40002146-187723 > for discussion of when to use "selection" vs. "selectedObjects".

In Figure 13, there are several combatants. Each combatant has a list of possible weapons to wield. There's an NSArrayController to manage that list. But which list should it manage, exactly? It should manage the list of available weapons for the _currently_selected_ combatant. The first NSArrayController is doing the tracking of the selection of combatant. So, this second array controller is bound to the "selection" of the first array controller to get at the selected combatant, and then using the "weapons" model key path to get that combatant's array of weapons.

The GUI designer wants the pop-up to contain all of the available weapons for the selected combatant, so it's content is bound to the arrangedObjects of the second array controller. As described in the NSPopUpButton bindings reference page, the pop-up will use the - description method to obtain a string from whatever kind(s) of objects are in the weapons array. If that weren't appropriate, you could bind the contentValues binding to arrangedObjects.name (assuming a weapon has a "name" property).

The pop-up should, of course, show the current selectedWeapon of the combatant as its selection. And, when the user picks a new weapon from the pop-up, it should set the combatant's selectedWeapon. So, the pop-up's selectedObject should be bound to the selected combatant's selectedWeapon property. Once again, where's the "selected combatant" being tracked? In the first array controller, as its "selection" property. So, the pop-up's selectedObject binding is bound to the first array controller, with Controller Key "selection", and Model Key Path "selectedWeapon".


The fact that some tutorials employ a custom controller and others don't is also confusing as I don't see the clear design rationale behind one and the other. Presumably you need a custom controller if you will have actions not provided automatically by the canned controllers (add, remove, insert, next, etc.). But the rationale for connections between the custom controller and NSController object also don't see that clear to me.

Typically, custom controllers are different kinds of things from NSController-derived objects. Search the Cocoa Fundamentals Guide for the phrases "mediating controller" and "coordinating controller".

Cheers,
Ken
_______________________________________________

Cocoa-dev mailing list (Cocoa-dev@lists.apple.com)

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

This email sent to [EMAIL PROTECTED]

Reply via email to