【问题标题】:NSWindow loses first responder after dismissing NSPopoverNSWindow 在关闭 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
  • 谢谢马雷克!肯定有一些提示。

标签: swift appkit first-responder responder-chain


【解决方案1】:

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

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

【讨论】:

  • 精彩的解释。谢谢!
猜你喜欢
  • 1970-01-01
  • 2019-07-01
  • 1970-01-01
  • 1970-01-01
  • 2012-05-17
  • 1970-01-01
  • 2011-04-07
  • 1970-01-01
  • 2017-10-17
相关资源
最近更新 更多