问题
我希望用户能够通过按 ESC 键来关闭窗口,但在这种特定情况下我无法让它工作,按 ESC 会触发错误声音(“不,你不能这样做” macOS bloop)并且没有任何反应。
上下文
我正在创建 NSWindowController 的子类,它本身创建 NSViewController 子类的实例并将其设置在 View 中。两个 Controller 都有自己的 xib 文件。
NSWindowController:
final class MyWindowController: NSWindowController, NSWindowDelegate {
@IBOutlet weak var targetView: MainView!
let myVC: MyViewController!
var params: SomeParams!
override func windowDidLoad() {
super.windowDidLoad()
myVC = MyViewController(someParams: params)
myVC.view.setFrameSize(targetView.frame.size)
myVC.view.setBoundsSize(targetView.bounds.size)
targetView.addSubview(myVC.view)
}
override var windowNibName: String! {
return "MyWindowController"
}
convenience init(someParams params: SomeType) {
self.init(window: nil)
self.params = params
}
}
NSViewController:
final class MyViewController: NSViewController {
convenience init(someParams params: SomeType) {
// do stuff with the params
}
override func viewDidLoad() {
super.viewDidLoad()
// configure stuff for the window
}
}
我尝试过的
我假设我的问题是 MyWindowController NSWindow 是 .initialFirstResponder
当我想要 targetView
(一个 NSTableView )成为第一个响应者 - 我猜这样我就可以使用 keyDown 并将关闭命令从那里发送到窗口。但这似乎并不是最佳选择。
我尝试通过在 MyWindowController 的 windowDidLoad 中使用 window?.makeFirstResponder(theView)
来强制 View Controller View 成为第一响应者,但没有任何变化。
我还尝试将其添加到 MyWindowController:
override func cancelOperation(_ sender: Any?) {
print("yeah, let's close!")
}
但这仅适用于如果用户首先单击窗口背景然后按 ESC,并且无论如何它仍然会发出错误声音。这实际上让我认为问题在于第一响应者在窗口上。
问题
你将如何实现这一目标?当然,我知道用户已经可以使用 CMD+W 关闭窗口,但我还是很想解决这个问题。
请注意,代码示例是用 Swift 编写的,但我也可以接受使用 Objective-C 的解释。
最佳答案
cancelOperation
的文档解释了 cancelOperation
应该如何工作:
This method is bound to the Escape and Command-. (period) keys. The key window first searches the view hierarchy for a view whose key equivalent is Escape or Command-., whichever was entered. If none of these views handles the key equivalent, the window sends a default action message of
cancelOperation:
to the first responder and from there the message travels up the responder chain.If no responder in the responder chain implements
cancelOperation:
, the key window searches the view hierarchy for a view whose key equivalent is Escape (note that this may be redundant if the original key equivalent was Escape). If no such responder is found, then acancel:
action message is sent to the first responder in the responder chain that implements it.
NSResponder
declares but does not implement this method.
NSWindow
实现了 cancelOperation:
并且下一个响应者(窗口 Controller )不会检查 cancelOperation:
的实现。 cancel:
消息确实到达窗口 Controller 。实现
- (void)cancel:(id)sender
{
NSLog(@"cancel");
}
会起作用的。 cancel:
消息不是从父类(super class)继承的,因此自动补全不建议这样做。
关于macos - 如何通过按 ESC 键关闭窗口(NSWindowController)?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42393336/