Ну, у меня есть клудж.
Я добавил логическое свойство shouldSwallowThisReturn. И я добавил строку, которая устанавливает для этого логического значения yes в селекторе send-action текстового поля:
switch (self.iNavMode) {
case kNavModeNeutral:
break;
case kNavModeSaveAndNew:
[self.window makeFirstResponder:self.btnSaveAndNew];
self.shouldSwallowThisReturn = YES;
[self.btnSaveAndNew setKeyEquivalent:@"\r"];
break;
case kNavModeSaveAndNext:
[self.window makeFirstResponder:self.btnSaveAndNext];
self.shouldSwallowThisReturn = YES;
[self.btnSaveAndNext setKeyEquivalent:@"\r"];
break;
default:
break;
}
И я добавил несколько строк в действие выбранной кнопки:
if (self.shouldSwallowThisReturn) {
self.shouldSwallowThisReturn = NO;
return;
}
[self.btnSaveAndNext setKeyEquivalent:@""];
Таким образом, остальные действия кнопки выполняются только после повторного нажатия кнопки возврата.
Это работает, но я бы предпочел более элегантное решение.
Дальнейшее изучение руководства Apple по обработке событий показывает, что не так: очевидно, когда вы используете IB для назначения отправленного действия текстовому полю, хотя действие отключается, когда пользователь нажимает return, этот возврат не регистрируется как ключевой эквивалент, и, следовательно, не отвечает да на запрос executeKeyEquivalent приложения, и поэтому приложение продолжает искать элемент управления, который ответит да, поэтому в конечном итоге он вызывает кнопку самостоятельно.
Похоже, что я действительно должен сделать, это создать подкласс текстового поля и переопределить его метод executeKeyEquivalent, чтобы он возвращал yes, если keyCode равен 36 (код для ключа возврата), например:
- (BOOL) performKeyEquivalent:(NSEvent *)theEvent {
printf("\nThe keycode is %d", [theEvent keyCode]);
if ([theEvent keyCode] == 36)
return YES;
else
return NO;
}
Но происходит то, что метод переопределения вызывается, даже если целевое текстовое поле не имеет фокуса. Действительно, он вызывается, даже когда выбранная кнопка уже является первым ответчиком. Поэтому теперь возврат пользователя всегда прерывается, и действие кнопки никогда не вызывается.
Я изменил метод переопределения, чтобы проверить идентичность firstResponder:
- (BOOL) performKeyEquivalent:(NSEvent *)theEvent {
printf("\nThe keycode is %d", [theEvent keyCode]);
if ([theEvent keyCode] == 36) {
ThisProject_AppDelegate *appDelegate = [[NSApplication sharedApplication] delegate];
id firstResponder = [appDelegate.windowController.window firstResponder];
if ([firstResponder isKindOfClass:[NSTextView class]]) {
printf("\nfirstResp is a field editor, a textview.");
if ([firstResponder delegate] == self) {
printf("\ntarget textfield is firstResponder.");
return YES;
}
}
else if ([firstResponder isKindOfClass:[NSButton class]]) {
printf("\nfirstResp is a button.");
return YES;
}
}
return NO;
}
Оказывается, переопределение вызывается после выполнения отправленного действия текстового поля, когда статус firstResponder уже передан кнопке. Таким образом, переопределение не помогает.
Пока что я застрял с кучей в верхней части этого ответа. Но должен быть какой-то способ заставить send-действие полностью захватить событие возврата ключа, которое его отключило ...