makeFirstResponder并不总是会触发

时间:2019-04-17 03:08:40

标签: swift macos cocoa nstoolbar nssearchfield

我在NSSearchField内有一个NSToolbar,我试图将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)
        }
    }
}

4 个答案:

答案 0 :(得分:1)

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

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

    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])")
        }
    }

答案 1 :(得分:1)

我发现了一个blog,促使我找到了发生这种情况的原因。在macOS中,默认情况下,NSWindow具有一个isRestorable布尔值,该值将撤回最后一个firstResponder的内容,而与设置为initialFirstResponder或设置为viewDidAppear内的内容等无关。

答案 2 :(得分:0)

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

不知道为什么。 数小时的挫败感。

答案 3 :(得分:-1)

实际上,makeFirstResponder总是使您的控件成为第一响应者,但不能保证下一个控件将不能成为第一响应者。

根据您的经验,当您在makeFirstResponder中调用viewDidLoad时,有一些控件将在您执行操作后要求firstResponder。因此,您的控件将失去焦点。

您可以通过在viewDidAppear中请求第一响应者或延迟1秒来解决此问题。