makeFirstResponder 并不总是触发

makeFirstResponder does not always fire

我在 NSToolbar 中有一个 NSSearchField,我试图将其设置为 makeFirstResponder,但它时断时续地工作。有时 NSSearchField 将成为第一响应者而不调用 makeFirstResponder 并且 makeFirstResponder 返回 true 就好像它已成功设置一样。设置 NSWindow.initialFirstResponder 也失败了。

class ViewController: NSViewController {
    override func viewDidAppear() {
        super.viewDidAppear()
        view.window?.makeFirstResponder(view.window?.windowController?.searchField
    }
}

我通过使用计时器延迟代码获得了一致的工作结果,但这是一个不太理想的解决方案。

class ViewController: NSViewController {
    override func viewDidAppear() {
        super.viewDidAppear()
        Timer.scheduledTimer(withTimeInterval: 1, repeats: false) { _ in
            self.view.window?.makeFirstResponder(self.windowController?.searchField)
        }
    }
}

如果 makeFirstResponder 正在返回 true,那么它可能至少在短时间内成为第一响应者。

您可以使用 NSWindow.firstResponder 符合 KVO 的事实,以便通过 ViewController class 中的以下代码检测对其的任何更改:

    override func viewDidAppear() {
        super.viewDidAppear()

        self.view.window?.addObserver(self, forKeyPath: "firstResponder", options: [.initial, .new], context: nil)
        self.view.window?.makeFirstResponder(self.windowController?.searchField)
    }

    override func observeValue(forKeyPath keyPath: String?, of object: Any?, change: [NSKeyValueChangeKey : Any]?, context: UnsafeMutableRawPointer?) {
        if keyPath == "firstResponder" {
            print("First responder of window: \(object) is \(change?[NSKeyValueChangeKey.newKey])")
        }
    }

我找到了一个 blog,它让我找到了发生这种情况的原因。默认情况下,在 macOS 中,NSWindow 有一个 isRestorable 布尔值,该值将调用最后一个 firstResponder 的内容,而不管设置为 initialFirstResponder 的内容或 viewDidAppear 中设置的内容,等等。

我发现调用 webView.makeFirstResponder() 没有任何作用。 但是调用 view.window?.makeFirstResponder(webView) 做到了。

不知道为什么。 几个小时的挫折。