从概念上讲,发生了以下情况:
- 只需调用
NSWindow.addTabbedWindow(_:ordered:)
即可将窗口添加到本机选项卡栏。
- 将
NSResponder.newWindowForTab(_:)
放入主窗口的响应者链中后,"+"按钮就会可见。
- 当您设置
window.tabbingMode =.preferred
时,选项卡栏将始终可见。
但是,在实现这些方法时存在一些注意事项。
实施newWindowForTab
那么何处添加@IBAction override func newWindowForTab(_ sender: Any?)
以便您可以调用NSWindow.addTabbedWindow(_:ordered:)
?
- 如果使用Storyboards,则将其放入您拥有的
NSWindowController
子类中。 这是获取NSWindow
以调用addTabbedWindow
的最简单方法。
- 如果使用Xib,则
AppDelegate
将引用主窗口。 您可以在此处放置该方法。
- 如果使用编程设置,请将其放置在您知道的主要
NSWindow
实例所在的位置。
使“+”按钮起作用
TL;DR:当您初始化新窗口时,请将窗口的windowController
存储在某个位置。 为了防止窗口事件(在控制器中)被处理,您需要维护强引用。
我编写了一个带有TabManager的示例应用程序来处理此问题:https://github.com/DivineDominion/NSWindow-Tabbing
以及详细信息的博客文章:https://christiantietze.de/posts/2019/07/nswindow-tabbing-multiple-nswindowcontroller/
考虑事件如何分派。主菜单消息沿响应者链发送,newWindowForTab
也是如此。如果调用源没有连接到最后——至少要连接到您的NSWindowController
,甚至可能要连接到您的AppDelegate
——则NSApp.sendAction
将无法处理标准事件。
您必须确保添加的任何其他窗口实际上都是与原始窗口相同的响应者链的一部分,否则菜单项将停止工作(并且变灰色/禁用)。 同样,当单击它时,“+”按钮停止工作。
这就是其他答案的评论中@JohnV所说的:“没有子视图变量,您无法创建多个选项卡”的效果。 这是效果,但不是真正的解释。 您始终可以创建更多选项卡,但只能从原始窗口/选项卡创建,而不是从新窗口创建; 这是因为另一个选项卡未响应newWindowForTab
。
“其他标签”本身只是NSWindow
。 您的newWindowForTab
实现位于控制器中。 那是上一级。
通过@Peter Ahlberg的代码进行调整,这将起作
class WindowController: NSWindowController {
@IBAction override func newWindowForTab(_ sender: Any?) {
let windowController: WindowController = self.storyboard?.instantiateInitialController() as! WindowController
let newWindow = windowController.window
self.window?.addTabbedWindow(newWindow, ordered: .above)
newWindow.orderFront(self.window)
newWindow.makeKey()
}
}
我不需要在AppDelegate
中添加newWindowForTab
就可以使用Storyboard使一切正常工作——因为这种方式窗口控制器可以继续工作而不需要回退!
newWindowForTab
以使来自我的Storyboard的视图出现。 - DaPhil