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 (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 arch...@mail-archive.com