如何确定NSSearchField / NSTextField是否具有输入焦点?

时间:2011-05-14 00:53:02

标签: cocoa macos

如何确定NSSearchField / NSTextField是否具有输入焦点?

3 个答案:

答案 0 :(得分:29)

之前的回答是错误的,因为NSTextField / NSSearchField本身不会成为第一个响应者并处理已编辑的文本。相反,他们使用窗口的字段编辑器,它是窗口上所有字段之间共享的NSTextView(因为它们中只有一个可以一次聚焦)。

您需要查看第一个响应者是否为NSText,如果是,则查询字段/文本字段是否为其委托。

NSResponder *firstResponder = [[NSApp keyWindow] firstResponder];
if ([firstResponder isKindOfClass:[NSText class]] && [(id)firstResponder delegate] == mySearchField) {
    NSLog(@"Yup.");
}

答案 1 :(得分:7)

Greg Titus'答案可能有效,我认为以下是更好的方法:

BOOL isFirstResponder = mySearchField.currentEditor == mySearchField.window.firstResponder;

答案 2 :(得分:0)

AppKit使用“字段编辑器”(即NSTextView)来处理NSTextField(或NSSearchFieldNSSecureTextField)中的实际编辑。当您的文本字段的窗口具有键盘焦点时,它会将字段编辑器作为子视图,而窗口的第一响应者是字段编辑器。

因此,通常,您可以检查文本字段是否具有字段编辑器:

if textField.currentEditor() != nil {
    // textField has the keyboard focus
} else {
    // textField does not have the keyboard focus
}

但是,当您将焦点移出文本字段时(通过按Tab键或单击另一个文本字段),该文本字段会发布NSControl.textDidEndEditingNotification(Objective-C :NSControlTextDidEndEditingNotification)。如果文本字段中有一个委托,并且该委托实现了control(_:controlTextDidEndEditing:)协议的NSControlTextEditingDelegate方法,则该通知也将被调用。

在传递此通知时(包括调用委托方法),文本字段仍将字段编辑器作为子视图,并且字段编辑器的委托仍设置为文本字段。因此,如果您不希望文本字段在通知处理程序(或委托方法)中仍然具有键盘焦点,那么测试字段编辑器将给出错误的答案。

(您可能会认为这是一个奇怪的测试,因为毕竟AppKit向您发送了一条通知,通知您文本字段不再是键盘焦点,所以为什么要问呢?但是您的通知处理程序可能会调用其他一些需要检查的方法,您不必传递一个标志,说“哦,顺便说一句,文本字段现在/现在不是键盘焦点”。)

好的,无论如何,在发送NSControl.textDidEndEditingNotification之前,AppKit会更改文本字段窗口的第一响应者。因此,您可以检查文本字段是否具有字段编辑器,以及该字段编辑器是否是其窗口的第一响应者。在处理NSControl.textDidEndEditingNotification时,此测试将报告该文本字段没有键盘焦点。

extension NSTextField {
    public var hasKeyboardFocus: Bool {
        guard
            let editor = currentEditor(),
            editor == window?.firstResponder
            else { return false }
        return true
    }
}