How can I determine whether an NSSearchField/NSTextField has input focus?
AppKit uses a “field editor” (which is an NSTextView
) to handle the actual editing in an NSTextField
(or an NSSearchField
or an NSSecureTextField
). While your text field has keyboard focus for its window, it has the field editor as a subview, and the window's first responder is the field editor.
So in general, you can check whether the text field has a field editor:
if textField.currentEditor() != nil {
// textField has the keyboard focus
} else {
// textField does not have the keyboard focus
}
However, when you move the focus out of the text field (by pressing the tab key or clicking in another text field), the text field posts an NSControl.textDidEndEditingNotification
(Objective-C: NSControlTextDidEndEditingNotification
). If the text field has a delegate, and the delegate implements the control(_:controlTextDidEndEditing:)
method of the NSControlTextEditingDelegate
protocol, then the delegate method is also called for the notification.
While this notification is being delivered (including calling the delegate method), the text field still has the field editor as a subview, and the field editor's delegate is still set to the text field. So if you don't want to consider the text field to still have the keyboard focus while in the notification handler (or delegate method), then testing the field editor will give the wrong answer.
(You might think this is a weird thing to test, because after all AppKit is sending you a notification that the text field is no longer the keyboard focus, so why do you need to ask? But maybe your notification handler calls into some other method that wants to check, and you don't want to have to pass in a flag saying “oh by the way the text field is/isn't the keyboard focus right now”.)
Okay, so anyway, before sending the NSControl.textDidEndEditingNotification
, AppKit changes the text field's window's first responder. So you can check whether the text field has a field editor, and whether that field editor is the first responder of its window. While you are handling the NSControl.textDidEndEditingNotification
, this test will report that the text field doesn't have the keyboard focus.
extension NSTextField {
public var hasKeyboardFocus: Bool {
guard
let editor = currentEditor(),
editor == window?.firstResponder
else { return false }
return true
}
}
The previous answer is wrong, because NSTextField
/ NSSearchField
do not themselves become the first responder and handle edited text. Instead, they use the window's field editor, which is an NSTextView
that is shared between all fields on the window (since only one of them can have focus at a time).
You need to see if the first responder is an NSText
, and if so, if the search field / text field is its delegate.
NSResponder *firstResponder = [[NSApp keyWindow] firstResponder];
if ([firstResponder isKindOfClass:[NSText class]] && [(id)firstResponder delegate] == mySearchField) {
NSLog(@"Yup.");
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With