0

In Aaron Hillegass' Cocoa Programming for Mac OS X, the Raiseman application connects a button in Interface Builder (IB) to an NSArrayController with sent action -remove:. In the MyDocument class he implements two KVC methods:

- (void)insertObject:(Person *)p inEmployeesAtIndex:(int)index;
- (void)removeObjectFromEmployeesAtIndex:(int)index;

When this button is pressed, the -removeObjectFromEmployeesAtIndex: method is called and the currently selected Person (Model) object is removed from the array.

  1. How does the remove: method used in IB cause the -removeObjectFromEmployeesAtIndex: method to be called?
  2. How do I reproduce this effect with an NSTreeController?
Dov
  • 15,530
  • 13
  • 76
  • 177
A A
  • 147
  • 1
  • 2
  • 8
  • What have you tried with the tree controller, and how did that fail? That would be useful information. – Dov Dec 13 '11 at 21:28
  • Say I have two node types: a Folder and a Person object. In IB, by setting the tree controller's object controller class name to either Folder or Person, I can add one or the other. But this does not allow adding either a Folder or a Person depending on the depth in the tree or by using a different pair of add and remove buttons. – A A Dec 14 '11 at 11:15

1 Answers1

0

If you want a simple built-in option, then it's only going to create an instance of the class you specified in IB. To create another instance, you're going to need to code it yourself. You should have all the information you need from the Tree Controller to insert the new class into the proper place in the hierarchy. Some diligent searching should give you the code you need.

To attempt to help you understand how the NSArrayController mechanism works, I'll explain the best I can from my knowledge of Objective-C and the runtime. Objective-C is a very dynamic language, and you can dynamically call selectors (methods). Since the NSArrayController knows the name of your class (e.g. "Employee"), its internal implementation probably looks something like the following (or easily could):

NSString *removeSelectorName = [NSString stringWithFormat:@"removeObjectFrom%@sAtIndex:",
                                self.objectClassName];
SEL removeSelector = NSSelectorFromString(removeSelectorName);

[dataRepresentation performSelector:removeSelector
                         withObject:[NSNumber numberWithInt:self.selectionIndex];

There are examples of this elsewhere in KVO, as with the +keyPathsForValuesAffecting<Key> method (documentation here), which describes which keys cause another key to be updated. If your key is named fullName and it updates whenever the first or last name changes, you would implement this in your class:

+ (NSSet *)keyPathsForValuesAffectingFullName {
    return [NSSet setWithObjects:
            @"firstName",
            @"lastName",
            nil];
}

Further searching (and this question) turned up this documentation page, which explains the semantics of how that method gets called.

Community
  • 1
  • 1
Dov
  • 15,530
  • 13
  • 76
  • 177
  • In any case, how does the remove: method used in IB cause the -removeObjectFromEmployeesAtIndex: method to be called with KVC? – A A Dec 14 '11 at 19:04
  • I had seen that question and documentation page previously. It says:"The default search pattern for mutableArrayValueForKey: is..." The issue is really: how someone would know that insert: calls mutableArrayValueForKey: (if in fact it does) - where is the documentation? Right now Hillegass and others use it but don't say how they knew to use it. Thank you. – A A Dec 15 '11 at 10:27
  • I'm not sure I'm clear on what you don't understand. Someone would know `-insert:` calls `-insertObject:inAtIndex:` by _reading the documentation_: that's why the documentation is there. – Dov Dec 15 '11 at 12:54