-1

In this document, Apple describes Accessor Patterns for To-One and To-Many properties. To-Many properties cover Indexed and Unordered collections.

Which brings me to the question:
Is there a different Accessor Pattern for tree structures, or should we use (or adapt) the same as for other types of collections?

Apparently, implementing Indexed To-Many accessors in my model and setting breakpoints in them has no effect when the NSArray holding the tree structure is bound to an NSTreeController. The model is updating correctly, e.g. when adding/removing elements, or changing their ordering, but the Accessor implementations are never called.

Am I missing something here?

insys
  • 1,288
  • 13
  • 26

1 Answers1

1

A tree is not one data structure in the same way that an array is. You either start with a single root node, in which case the property is a to-one relationship to that node, or an array of top-level nodes, in which case the property is a to-many relationship to those nodes. The other levels of the tree are separate relationships from those root nodes, not from the object providing the root nodes.

NSTreeController is configured with a children key path. It uses that key path on each node to access the children of each node. If it's adding or removing nodes, that would be a mutation of the children of the parent node via KVC. (It probably uses -mutableArrayValueForKeyPath: on the parent and then NSMutableArray methods on the resulting proxy.) That should go through the index collection mutation accessors on the parent object.

Are you sure you implemented the accessors on the correct class (and set the breakpoints on them)?

The framework really has no choice other than to use KVC to access and mutate your property. KVC will use your accessor methods if they are property named. Depending on how you implemented your class, KVC may have no choice other than to call your accessor methods. For example, you can implement an indexed collection property without any array-typed getter or setter or any array instance variable to back it (or it could have an instance variable whose name is completely unrelated to the property name).

For example, a class could implement:

- (NSUInteger) countOfEmployess;
- (id) objectInEmployeesAtIndex:(NSUInteger)index;
- (void)insertObject:(id)anObject inEmployeesAtIndex:(NSUInteger)index;
- (void)removeObjectFromEmployeesAtIndex:(NSUInteger)index;

without any -employees or -setEmployees: accessors nor any employees or _employees instance variable. It would still be completely KVC-compliant for an indexed collection property named "employees". If an NSTreeController were given such a node and configured to use "employees" as the children key path, it could manipulate that node's employees just fine. What could it use if not those accessor methods?

Just for good measure, be sure to implement +accessInstanceVariablesDirectly to return NO in all of your custom classes. That can catch things like misspelled methods/property names.

Ken Thomases
  • 88,520
  • 7
  • 116
  • 154
  • Thanks for the explanation, it makes sense. I've created a test project and verified that KVC methods are indeed being called on add/remove etc. The culprit here turned out to be the -moveNodes:toIndexPath: method of NSTreeController, which evidently does not use the standard KVC methods to perform it's duty. I'll accept your answer and open a new question on that topic. – insys May 17 '15 at 19:59