views:

334

answers:

2

I have a text field cell in a table view, from which I need to be made aware when it ends editing. I thought I would set my Controller class as the text field cell's delegate, and then use NSTextField's delegate method textDidEndEditing:, but realized that the text field cell doesn't seem to have delegate methods? Why is this, and what can I do (other than subclassing) to be informed when editing is finished?

Thanks

+3  A: 

NSTextFieldCell inherits from NSCell (well, technically from NSActionCell which inherits from NSCell). The NSCell class is used to (from the docs):

The NSCell class provides a mechanism for displaying text or images in an NSView object without the overhead of a full NSView subclass.

Notably, The cell class is used for "displaying text or images", and not dealing with interaction with the user. Similarly, with the NSTextField class:

The NSTextField class uses the NSTextFieldCell class to implement its user interface.

The NSTextField deals with the actual user input, whilst using the text field cell to simply implement its user interface, and similarly, the delegate methods to provide notification when the editing of text has ended is provided through the NSTextField class and not through the NSTextFieldCell class.

If you want to be notified of when editing ends in an NSTableView, then you need to register yourself as an observer of the NSTextDidEndEditingNotification (you might want to read the NSNotificationCenter class reference if you are unfamiliar with notifications). To do this, place the following in your controller class; the awakeFromNib function is a good place to include it to ensure that it is called upon your application's startup:

NSNotificationCenter *nc = [NSNotificationCenter defaultCenter];
[nc addObserver:self
       selector:@selector(textDidEndEditing:)
           name:NSTextDidEndEditingNotification
         object:tableView];

Where tableView is the pointer to your NSTableView object. Then, simply implement the method as follows:

- (void)textDidEndEditing:(NSNotification *)aNotification
{
    // Do what you want here
}

Don't forget to remove yourself as an observer upon deallocation:

- (void)dealloc
{
    NSNotificationCenter *nc = [NSNotificationCenter defaultCenter];
    [nc removeObserver:self];
}

The reason that you set the object that you are observing to be the NSTableView instance (and not the cell itself) is that under the hood, when you edit a cell in the table, the cell that you are dealing with isn't being edited directly; it is the window's (or a custom) field editor. When editing ends, the field editor then passes the new value for that cell on to the table view. However the table view will post a notification to say that a cell has finished being edited.

Perspx
What about the 'TextDidEndEditing:' method?
Walker Argendeli
Apologies, take a look at the edits; I remembered that the tableView:shouldEditTableColumn:row: is called at the beginning of editing.
Perspx
“The reason that this is placed in the NSTableView class…” I thought this was in the controller.
Peter Hosey
Fixed what I was trying to convey.
Perspx
A: 

Implement the tableView:setObjectValue:forTableColumn:row: method in the NSTableViewDataSource protocol. Put it next to the tableView:objectValueForTableColumn:row: method that you've already implemented.

- (void)tableView:(NSTableView *)aTableView
   setObjectValue:(id)anObject
   forTableColumn:(NSTableColumn *)aTableColumn
              row:(NSInteger)rowIndex
{
    [mutableArrayWithStrings replaceObjectAtIndex:rowIndex withObject:anObject];
}
Arne Evertsson