NSTextField按回车键触发操作。

12

我一直在寻找一个简单的示例,演示如何在文本字段中按下回车键时触发操作(或按钮)。

我需要继承文本字段吗?我需要设置委托来调用所需的操作吗?有没有办法在我的主窗口控制器类中捕获事件?

如果您能指导我方向,那就太好了。谢谢。

5个回答

22

参考答案评论中提到的网站现在被主机商“暂停”,而 Google 缓存中也没有包含关键步骤的截图。

以下是我发现的另一种解决方案:

  1. 完美地运作
  2. 不需要子类化

对于某些按键(如 Enter、Delete、Backspace 等),苹果公司不会调用常规的 controlTextDidEndEditing: 等方法。相反,苹果公司为每个幻数键提供单独的选择器 - 但有一个方法可以拦截它。

苹果公司的官方文档在此处:

https://developer.apple.com/library/mac/documentation/TextFonts/Conceptual/CocoaTextArchitecture/TextEditing/TextEditing.html#//apple_ref/doc/uid/TP40009459-CH3-SW31

...但如果该文档消失/移动了,请将此方法添加到您的代理中:

- (BOOL)control:(NSControl *)control textView:(NSTextView *)fieldEditor doCommandBySelector:(SEL)commandSelector
{           
    BOOL retval = NO;

    if (commandSelector == @selector(insertNewline:)) {

        retval = YES; // causes Apple to NOT fire the default enter action

        // Do your special handling of the "enter" key here

    }

    NSLog(@"Selector = %@", NSStringFromSelector( commandSelector ) );

    return retval;  
}

在我的情况下,我想覆盖退格键 - 运行这个方法后,我得到的输出结果显示选择器是"deleteBackward:",所以我在那里添加了另一个if语句来针对它做出反应。


如果您想在NSTextView的完成弹出窗口打开时捕获回车键,那么此方法将无法工作,因为doCommandBySelector:不会被调用。相反,您可以在controlTextDidChange:中观察[[NSApp currentEvent].charactersIgnoringModifiers isEqualToString:@"\r"] - lhunath

9

当你按下回车后,可以在窗口控制器中编写一个IBAction并将其连接到文本字段以获取操作。如果您希望更多功能,例如当您聚焦于文本字段并离开文本字段时应调用您的方法,则需要设置委托(请参考此处)。


2
嗨,谢谢,我已经做到了,但是如何过滤回车键呢?因为当他们聚焦或从文本字段模糊时,动作也会触发。谢谢 - Chris
为了在编辑文本完成时(按下回车键或标签键)获得通知,委托类的controlTextDidEndEditing方法将被调用,在那里您可以触发动作。如果您只想为回车键触发操作,则必须编写自定义格式化程序或定制的NSTextfield类。 - Raviprakash
1
谢谢,Gudda。我刚刚发现你可以按照这里所述的方式仅在按下回车时发送操作:http://mojomonkeycoding.com/2009/11/14/calling-an-action-when-hitting-return-in-an-nstextfield/。所以幸好不需要子类化。 - Chris
2
mojomonkeycoding.com网站现在已经关闭,真是太遗憾了。最终,我找到了一种在代码中干净地完成它的方法 - 没有子类化 - 参见下面的答案。 - Adam
上帝保佑你!你拯救了我的理智。 - DesperateLearner
为了确保只有在按下回车键时才会触发操作,而不是在失去焦点时也触发操作,请在Storyboard中选择NSTextField并将Action更改为“仅在按下回车键时发送”在Attributes Inspector中。 - Jordan H

2

只需将您的控制器类的IBAction与文本字段连接即可。当您按下Enter键或使用Tab或鼠标离开文本字段时,应调用该操作。


1

对于好奇的人,这里是如何实现-controlTextDidEndEditing:(NSNotification)obj的方法(如果您不关心仅响应回车键)

AppDelegate.h:

// Conform to the protocol to avoid compiler warnings
@interface myClass : NSObject <NSTextFieldDelegate>

// Link up to the interface elements you want to trigger
@property (weak) IBOutlet NSTextField *myTextField;
@property (weak) IBOutlet NSButton *myButton;

// Create an action linked to myButton
- (IBAction)myButtonPressed:(id)sender;

// Advertise that you implement the method
- (void)controlTextDidEndEditing:(NSNotification *)obj;

AppDelegate.m:

@synthesize myTextField = _myTextField;
@synthesize myButton = _myButton;

// Make yourself the delegate
- (void)applicationDidFinishLoading:(NSNotification *)aMessage {
    _myTextField.delegate = self;
}

// NSTextField objects send an NSNotification to a delegate if
// it implements this method:

- (void)controlTextDidEndEditing:(NSNotification *)obj {
    if ([[obj object] isEqual:_textField]) {
        [self myButtonPressed:nil]; // nil = sender
    }
}

对我来说非常有效。


1

最好的做法是使用 control + drag 到你已经创建的操作,这样按下 return 也会触发该操作。


5
是的。此外,如果你的Interface Builder不是非常老旧的版本,你可以选择你的NSTextField,打开属性检查器,并将动作改为“仅在按下回车键时发送”而不是“完成编辑时发送”。这样就可以轻松地使NSTextField在例如Web浏览器的URL字段中正确地运作。 - user1985657

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接