Re: bindings duplicates object returned
Re: bindings duplicates object returned
- Subject: Re: bindings duplicates object returned
- From: Quincey Morris <email@hidden>
- Date: Wed, 07 Dec 2011 21:34:23 -0800
On Dec 7, 2011, at 20:05 , Eric Slosser wrote:
> I have an NSTreeController whose 'content array' is bound to another object's 'content' key.
>
> It appears that the binding mechanism duplicates the array that was returned by [foo content].
>
> This is bad, because changes that 'foo' makes later to its m_content never show up in the window. It's also bad because [NSTreeController selectedObject] doesn't correspond to anything in the tree under [foo content].
>
> I can work around this by NOT using bindings to establish the controller's content, instead using [NSTreeController setContent:].
>
> 1. Where in the docs is this binding duplication described?
> 2. Is there a way to use bindings and avoid having [foo content] duplicated?
Based on this information, the problem is that your Foo class isn't KVO compliant for the "content" property.
Conceptually, it's a mistake to think of "content" as an array property (that is, as a property that has an array as its value). Conceptually, you should think of it as an indexed to-many relationship.
The correct approach is to properly implement the KVC indexed collection accessors in your Foo class**. See:
http://developer.apple.com/library/mac/#documentation/Cocoa/Conceptual/KeyValueCoding/Articles/AccessorConventions.html#//apple_ref/doc/uid/20002174-BAJEAIEE
Normally, you need to write only the 'insert' and 'remove' accessors. You can let all of the others default. Then, when changing the value of the property, you should never change m_content directly***. Instead, use the collection accessors, or use the mutable array proxy. For example, to add an object to the array, use either of these:
[foo insertObject: newObject inContentAtIndex: newIndex]; // or …
[[foo mutableArrayValueForKey: @"content"] insertObject: newObject atIndex];
Both of these are KVO compliant, and functionally equivalent.
Once you have this machinery set up, your binding to Foo's "content" should work properly.
** Of course, in practice, the Foo instance has to return *some* object that looks like an array as the value of the "content" getter, since properties have types. But think about what object ought to be returned. You don't want to return your 'm_content' array, because you're exposing an implementation detail to clients of your Foo class. You don't want to return a copy of your 'm_content' array, because that of course won't change after being created.
Catch-22, isn't it? Ideally, the Foo instance would return [self immutableArrayValueForKey: @"content"] but unfortunately there's no such method. The simplest choice is probably to return the ivar, but to write no code that uses the @property value.
*** When using an array ivar to back an indexed collection property like this, it's safe to modify the ivar directly in the init method only (because there aren't any observers at this point). Apart from that method, you should always use the KVO compliant accessors.
_______________________________________________
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