Re: NSArrayController's contentArray and selectedIndexes don't match when sorted
Re: NSArrayController's contentArray and selectedIndexes don't match when sorted
- Subject: Re: NSArrayController's contentArray and selectedIndexes don't match when sorted
- From: Matt Neuburg <email@hidden>
- Date: Mon, 06 Mar 2006 11:33:23 -0800
- Thread-topic: NSArrayController's contentArray and selectedIndexes don't match when sorted
On Sun, 05 Mar 2006 17:14:13 -0800, Greg Herlihy <email@hidden> said:
>A binding is a much tighter kind of relationship than the one between an
>observer and an observed. A binding makes two properties in two separate
>places, behave as if they were one and the same.
>
>Binding the selectionIndexes of the NSArrayController to your own variable,
>means that the set of selected objects in the array controller is a matter
>decided strictly between your variable and the array controller itself. It
>means that a change in either location automatically makes the identical
>change in the other place. As long as the two are bound, they will always
>agree with each other.
>
>Unfortunately, this binding between your variable and the NSArrayController
>leaves no room for the table at all. So whatever is selected in the table
>changes nothing about the selection in the NSArrayController (or in its
>bound variable). So there is no reason to expect that the selection in the
>table would match the selection in the NSArrayController, because no binding
>exists between them.
>
>To have the table selection mirror the selection in the NSArrayController,
>requires binding the table's selectionIndexes to the selectionIndexes in the
>NSArrayController (and this is a typical binding for most apps). Binding the
>table's selectionIndexes to the corresponding property in the
>NSArrayController, will also eliminate a need to have an observer. The table
>selection itself will show exactly what is selected in the NSArrayController
>- since with the two selections being bound to each other, there is no
>possibility for any disagreement to exist between them.
This was an interesting lecture but it is wrong on the law and wrong on the
facts.
THE LAW
There is nothing special about the "tightness" of bindings; bindings don't
work by some sort of magic, and they are not in fact all that different from
observing (in fact, they involve observing). And the phenomenon I am
describing, which is not actually very much of a problem since, as I said, I
know how to solve it, has nothing to do with "leaving no room for the table
at all".
THE FACTS
(1) It is wrong to claim that "there is no reason to expect that the
selection in the table would match the selection in the NSArrayController";
they *do* match. Indeed, if you try for yourself what I'm describing, or if
you just read my description of it carefully, you will see that the table is
NOT left out of the picture - just the opposite, in fact, which is exactly
what was giving me trouble. When you bind an NSTableColumn to an
NSArrayController's arrangedObjects, the sort descriptors are automatically
bound through for you. This is easy to prove: just sort the table (in the
interface) and examine the NSArrayController's sortDescriptors. They've
changed! Indeed, the mere fact that (as I said originally) the
selectedIndexes are reported with respect to the current sort order in the
interface, proves that the NSArrayController knows how the interface is
sorted.
(2) It is wrong to tell me to bind the table's selectionIndexes to the
selectionIndexes in the NSArrayController or to claim that this is a typical
binding for most apps. If this is how *you're* doing it typically, you're
doing it atypically. :) For one thing, if you do that, plain and simple,
then the table will come up blank! If you bind the table's selectionIndexes,
you must also bind its content (and sortDescriptors?).
(3) It is wrong to tell me that binding the table's selectionIndexes will
solve the problem. If you *do* bind the table's content, selectionIndexes,
and sortDescriptors to the NSArrayController, the behavior of the app
remains exactly the same as I described before.
CONCLUSION
mmalc's response is, of course, spot on: I can either sort the bound content
array myself using the sortDescriptors, and then the selectedIndexes will
match up with it, or I can stop being so obsessive and just use an outlet to
the darned NSArrayController in the first place. I've done the latter - but
as mmalc points out, I don't have to if I really, really don't want to.
Originally I was surprised that the NSArrayController's selectedIndexes and
its contentArray bound info didn't match up, but since, as mmalc points out,
I get filterPredicate and sortDescriptors bindings as well, I have all the
information I need if I wanted to use a pure bindings solution, which
answers my question. Thx - m.
>On 3/5/06 11:36 AM, "Matt Neuburg" <email@hidden> wrote:
>
>> I am managing an NSTableView by binding it's columns in the ordinary way to
>> an NSArrayController. I have bound the NSArrayController's contentArray and
>> selectedIndexes to ivars in MyObject so that MyObject can examine what's
>> going on in the table without an outlet to either the table or to the
>> NSArrayController.
>>
>> Except that it isn't working because if the user sorts the table, the
>> selectedIndexes and the contentArray don't match up any more.
>>
>> Example:
>>
>> * The table is not sorted. The user selects the first row. The
>> selectedIndexes tells me that item 0 is selected, and the object at index 0
>> of the contentArray is "Moe". So far so good.
>>
>> * The user sorts the table and selects the first row. The selectedIndexes
>> tells me that item 0 is selected. The object at index 0 of the contentArray
>> is still "Moe". But the first row of the table says "Mannie". Ooops!
>>
>> In other words, the selectedIndexes is describing the table as it actually
>> appears; it is not telling me the indexes in the underlying contentArray
>> that are selected.
>>
>> So how can I learn what indexes of the contentArray are actually selected in
>> the table?
>>
>> Now, you'll probably say: "Well, you schlumpf, just make an outlet to the
>> NSArrayController and examine its selectedObjects. That's way simpler than
>> what you were doing before anyway (because you no longer have to interpret
>> an NSIndexSet)." That's true, but still I don't really want to do that. I
>> really like the way bindings from the NSArrayController allow me to
>> "project" facts about the table directly into ivars of MyObject; to me, this
>> is a majorly cool feature of bindings. I like doing that better than
>> "peeking" into the NSArrayController through an outlet. So, is there a way
>> to do it my way, or is it just Tough Nuggies? m.
>
>
>
>
>
--
matt neuburg, phd = email@hidden, <http://www.tidbits.com/matt/>
A fool + a tool + an autorelease pool = cool!
AppleScript: the Definitive Guide - Second Edition!
<http://www.amazon.com/gp/product/0596102119>
_______________________________________________
Do not post admin requests to the list. They will be ignored.
Cocoa-dev mailing list (email@hidden)
Help/Unsubscribe/Update your Subscription:
This email sent to email@hidden