【问题标题】:How to determine whether an NSSearchField/NSTextField has input focus?如何判断一个 NSSearchField/NSTextField 是否有输入焦点?
【发布时间】:2020-02-05 05:17:18
【问题描述】:

如何判断一个 NSSearchField/NSTextField 是否有输入焦点?

【问题讨论】:

  • 我的回答实际上是不正确的。我已经对其进行了编辑,以便您可以删除复选标记。请参阅 Greg Titus 的回答。

标签: cocoa macos


【解决方案1】:

前面的答案是错误的,因为NSTextField / NSSearchField 本身并没有成为第一响应者并处理编辑的文本。相反,他们使用窗口的字段编辑器,这是一个NSTextView,在窗口上的所有字段之间共享(因为一次只能有一个字段具有焦点)。

您需要查看第一响应者是否为NSText,如果是,则搜索字段/文本字段是否为其代表。

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

【讨论】:

  • 关于我的错误非常正确;好答案! (您应该给我留言。)一个小提示:您需要将指针投射到搜索字段,因为delegate 返回id
  • 我最终对我的问题使用了不同的解决方案,无论如何我觉得更好,并且不需要我知道 NSTextField 是否有输入焦点,但感谢您的回答,我一定会记下它以备将来参考。 +1
  • 你如何翻译 swift (id)firstResponder delegate = mySearchField
【解决方案2】:

虽然 Greg Titus 的回答可能有效,但我认为以下是更好的方法:

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

【讨论】:

  • 这是一种更干净的方式。
【解决方案3】:

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:@ 987654327@)。如果文本字段有一个委托,并且该委托实现了NSControlTextEditingDelegate协议的control(_:controlTextDidEndEditing:)方法,那么该通知也会调用该委托方法。

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

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

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

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

【讨论】:

  • 我可以在我的 NSSearchFieldDelegate 中的某个地方调用这个方法来确定搜索栏是否处于焦点?
  • 可能,因为NSSearchFieldNSTextField 的子类。
  • 但是我在哪里使用它呢?我尝试在controlTextDidChangecontrolTextDidEndEditingcontrolTextDidBeginEditing 中使用它。在所有情况下,它总是报告搜索字段是焦点。检查textField.currentEditor() == nil 是否需要注册NSControl.textDidEndEditingNotification 也是如此。如果是这样,我该怎么做?
  • 就我而言,我不需要在预定时间检查如果搜索字段处于焦点位置,何时 搜索字段进出焦点。
猜你喜欢
  • 2010-10-02
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2010-11-22
  • 2019-05-27
  • 2021-01-11
  • 1970-01-01
相关资源
最近更新 更多