Re: Binding NSTextField to an array
Re: Binding NSTextField to an array
- Subject: Re: Binding NSTextField to an array
- From: Quincey Morris <email@hidden>
- Date: Mon, 06 Mar 2017 14:07:35 -0800
On Mar 6, 2017, at 11:31 , Jeremy Hughes <email@hidden> 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 (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