NSWindow 在关闭 NSPopover 后失去了第一响应者

Posted

技术标签:

【中文标题】NSWindow 在关闭 NSPopover 后失去了第一响应者【英文标题】:NSWindow loses first responder after dismissing NSPopover 【发布时间】:2019-02-13 12:41:41 【问题描述】:

我有一个窗口,它显示一个带有一堆文本字段的弹出框。我希望这些文本字段在弹出框出现时是可选项卡但不集中的。为了实现这一点,我在弹出框出现时将第一响应者设置为nil

// Inside popover's view controller.
override func viewDidAppear() 
    self.view.window!.makeFirstResponder(nil)

这工作正常,直到弹出框被解除导致拥有窗口的第一响应者被设置为窗口本身,而不是在弹出框出现之前作为第一响应者的视图。但是,如果我在上面的块中执行 self.view.window!.makeFirstResponder(self.view) 或根本不触摸第一响应者,一切都会按预期工作,并且当弹出框被解除时,拥有窗口的第一响应者会正确恢复。

据我所知,popover 内部的变化不应该影响拥有的窗口,因为 popover 有自己的窗口和自己的响应者链。

我很好奇幕后发生了什么。很确定这取决于响应者链的工作方式和更新方式,但我无法连接这些点。

–––

谁能解释为什么当弹出框被解除时,将弹出框内的第一响应者更改为nil 会扰乱拥有窗口(在其上方显示)的第一响应者?并且在使用上述解决方法时不会影响它?

【问题讨论】:

新打开的 popover 没有初始的 key 响应者,不能成为 key。您的代码手动强制第一响应者(关键事件)成为窗口。弹出窗口关闭屏幕后,您需要手动恢复第一响应者(因为您将其设置为 nil)。 嗯。好的。但是为什么拥有窗口会关心弹出框及其窗口内发生的事情呢?据我了解,响应者链是窗口本地的,一旦弹出窗口出现,它就是独立的。没有? 因为弹出窗口显示在隐藏窗口中,而底层窗口是它的父窗口。子窗口 - 不接受关键事件。不是 100% 确定这一切,但您可以使用 Hopper 分解 AppKit 以查看发生了什么。还要看看 recalculatekeyviewloop mikeabdullah.net/nspopover-key-view-loop.html 和 ***.com/questions/34612744/… 谢谢马雷克!肯定有一些提示。 【参考方案1】:

弹出窗口是所属窗口的子窗口,并与其父窗口共享第一响应者。当弹出窗口关闭时,_NSPopoverCloseAndAnimate: 被调用。如果弹出框的第一响应者是NSView 的子类,则在所属窗口上调用_updateFirstResponderForIgnoredChildWindow: 并将设置第一响应者。如果弹出框的第一响应者是一个窗口,则所属窗口的第一响应者不会恢复。

如果弹出框不包含任何可以作为第一响应者的视图,则所属窗口的文本字段将保持第一响应者并接受按键。

【讨论】:

精彩的解释。谢谢!

以上是关于NSWindow 在关闭 NSPopover 后失去了第一响应者的主要内容,如果未能解决你的问题,请参考以下文章

关闭 NSWindow 后无响应的 UI 元素

弹出框在状态栏中时的 NSPopover 瞬态

在 Swift 中打开一个关闭的 NSWindow 会导致应用程序崩溃

如何以编程方式关闭全屏模式NSWindow?

NSTableView 意外调整大小

在 Macbook PRO 中关闭 NSWindow 时 CEF 崩溃(仅在触摸板上不用于鼠标单击)