Context
Mac OS X 10.8 and later
I have a view-based NSTableView with default NSTableCellView (i.e. a NSTextField) which is inside a dialog sheet. There are also a Cancel and a OK button with their default shortcuts set (respectively Escape and Return).
Problem
When the edition of a cell of the tableview is ended via the Return key, the sheet gets also closed. I don't want this.
Regression
This kind of problem does not happen with a cell-based NSTableView.
Investigation
When looking at the backtrace, the sheet gets closed because the OK button action is invoked via its shortcuts. What happens is that the edited NSTextField calls [self.window performKeyEquivalent:] when its textDidEndEditing: method is invoked with NSTextMovement == @(
NSReturnTextMovement)
I had a look at the reconstructed code of [NSTextField textDidEndEditing:] (via Hopper) and while I can find the [self.window performKeyEquivalent:]; I haven't been able to figure out whether there is a way to prevent this from happening.
- Playing with the didEndEditing and beginEditing NSTextField delegate methods/notifications looks like a deadend.
- Overiding performKeyEquivalent: for NSWindow subclasses is not recommended and is not producing any expected behaviors.
Question
Is there a way to get back the appropriate behavior we had with cell-based NSTableView (the edition of the text field ends and that's all) and disable the incorrect behavior of view-based NSTableView?
I'm probably missing something obvious.
I've found a solution that works at least on OS X 10.10. I haven't yet checked on other OS versions.
It requires to subclass NSTableCellView and make the subclass to "support" the NSTextFieldDelegate protocol.
Then you set the delegate of text field of the table cell view to be the table cell view.
Then in the NSTableCellView subclass, you add this:
- (BOOL)control:(NSControl *)inControl textView:(NSTextView *)inTextView doCommandBySelector:(SEL)inSelector
{
if (inSelector==@selector(insertNewline:))
{
[inControl.window makeFirstResponder:self];
return YES;
}
return NO;
}