On Mar 6, 2017, at 11:31 , Jeremy Hughes <moon.rab...@virginmedia.com> wrote:
> 
> But I wonder if it is possible to bind directly to an array of NSNumbers 
> without using a wrapper.

No, but the reason for that and for the trouble you’ve run into is a bit 
complicated.

First of all, you are actually talking about bind *through* an array of 
NSNumbers, overall, not to *it*. You can never bind through an array of 
anything. It’s a limitation of KVC, and nothing to do with NSArrayController in 
any direct sense.

Array controllers have two, asymmetrical, sides. On the content side, there’s a 
content collection of some sort, typically modeled as an array. This *can* be 
set up with a content binding, but it isn’t the only way — it can be a 
connection instead. The fact that you chose to use a content binding is 
irrelevant to to everything else that’s going on.

The objects vended by the array controller are a collection of values obtained 
from the content array, but filtered and sorted internally by the array 
controller. Of those objects, if you go through the “selection” or 
“selectedObjects” properties, you only “see” what is selected. When the client 
side binding is to a scalar control such as a text field, the client side 
objects aren’t functionally an array. Instead, you either have a single object 
(*the* selected object) which is bound as an individual, or a single marker 
object representing the multiple selection. There is magic (pseudo-magic) 
within the array controller that translates between the single object behavior 
of the control and the array of selected objects that it maintains internally.

All of this you’ve already discovered experimentally, but there’s nothing going 
on on the client side that functionally binds to or through an array. The array 
controller is doing something clever (pseudo-magical) instead. You are in fact 
binding only to single objects, and the array controller kinda turns this into 
binding to multiple single objects at the same time.

That’s why it breaks when you try to edit the values. When you bind a text 
field to a single object, the object must be mutable or you can’t change its 
value. Binding to “selection” or “selectedObjects” has similar semantics, and 
fails if the objects are not individually mutable. In your case, it’s your 
underlying array that’s mutable, not your values, and that’s not good enough.

OK, so what we’re really talking about is binding to immutable objects. I’m not 
sure that I’ve ever run into the case of using NSNumber objects, but I have run 
into the case of using NSString objects. That’s even weirder, because there are 
mutable strings, but they’re a different class — NSMutableString instead of 
NSString. You can editably bind to a single NSMutableString value, but it 
probably won’t work for very long because it’s also a NSString, and the mutable 
string will probably end up getting replaced by an immutable string pretty 
soon, and after that things will fall apart. With NSNumber things just fall 
apart immediately, which saved you some time of going further down the wrong 
path.

The clue to all this was the hack of using “self” as a model key. (You can also 
leave the model key blank to mean the same thing, although in some key fields 
IB might force you to enter something, hence the “self”.) It’s not that it’s 
wrong, and if your text field was not editable you would have already had a 
working solution, but that it signals that you’re not properly working with 
*properties of objects*, which is the essence of both KVC and bindings. You 
were in effect trying to work with objects without properties, your NSNumber 
objects.

That’s why your Number wrapper approach was both the right thing to do and 
worked. Now, you had objects with a “value” property that you could bind to. I 
realize it feels wasteful to have custom objects with no other properties, but 
I’m guessing, if you think this through in larger terms, that you may find that 
this value is really a property of a more complicated model object, and that 
you should be setting your array controller’s content to a collection of those 
more complicated model objects. (Perhaps.)

The takeaway here, the moral of the story, is that taking shortcuts with KVC 
and bindings — using standard objects such as arrays, dictionaries, numbers and 
strings — almost always gets you into trouble as soon as you exceed the 
simplest of app requirements. You really must think in terms of properties, not 
values. Once you do that, everything falls into place and it becomes clear what 
to do.

_______________________________________________

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

This email sent to arch...@mail-archive.com

Reply via email to