Thanks for the pointers, Quincy.  However, I implemented the following 
accessors, checked I wasn't directly touching m_contents except in my init, and 
the problem persists.

    - (void) setContents:(id)newValue
    - (NSUInteger)countOfContents
    - (id)objectInContentsAtIndex:(NSUInteger)idx
    - (void)insertObject:(id)obj inContentsAtIndex:(NSUInteger)idx
    - (void)removeObjectFromContentsAtIndex:(NSUInteger)idx

I implemented -(BOOL)[Foo respondsToSelector:] to see what else I might be 
missing, but Foo is only asked about '_finishedMakingConnections'  and 
'_autounbinder'.  If I'm still missing an accessor, it must be determined 
without using respondsToSelector:.

On Dec 8, 2011, at 12:34 AM, Quincey Morris wrote:

> 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

Reply via email to