如何从以编程方式新创建的选项卡的视图控制器与 window 控制器通信?

How to communicate to the window controller from view controller of newly, programmatically created tab?

在我的 window 控制器中,我实现了:

    @IBAction override func newWindowForTab(_ sender: Any?) {
        
        if let wc = NSStoryboard.main?.instantiateInitialController() as? WindowController,
            let window = wc.window {
            
            self.window?.addTabbedWindow(window, ordered: .above)
            window.makeKey()
        }

        
    }

在视图控制器中,我有这段代码:

let window = self.view.window?.windowController as? WindowController

也尝试过:

let window = NSApp.mainWindow?.windowController as? WindowController

如果我没有任何选项卡,它可以获取 window 控制器。但是在新标签页上,它确实抓住了 window 控制器。

同样,我尝试向 WindowController 发送操作但未成功:

NSApp.sendAction(#selector(WindowController.pageLabelChange), to: nil, from: label)

适用于原始 window,但不适用于任何新创建的标签。

新创建的视图控制器对象如何与window控制器通信?

编辑:

有关我如何使用此代码的更多上下文:它基本上是一个嵌入 window 中的 PDFView。 window 有一个显示页码的工具栏。使用上面的任何代码,我可以设置 PDFView 的当前页码,但是当有一个选项卡时,它不起作用。使用 .PDFViewPageChanged 通知,我调用 func

NSApp.sendAction(#selector(WindowController.pageLabelChange), to: nil, from: pdfView)

编辑 2:

我创建了一个 GitHub 和一个 test project that shows the problem I have。您应该能够看到,当您启动项目时,+ 按钮将向选项卡栏中的文本字段添加一个数字。但是,如果您转到“查看”菜单 >“添加”选项卡,它会创建一个新选项卡,但 + 什么都不做。

您在堆栈上创建了新的 window 控制器,因此它会在 return 之后立即销毁,这就是原因。您需要在某处存储对创建的选项卡 window 控制器的引用并对其进行管理(存储位置取决于您的应用程序逻辑)。

这是使代码正常工作的简单演示

测试 Xcode 11.4 / macOS 10.15.5

final class WindowController: NSWindowController {
    @IBOutlet weak var testField: NSTextField!

    var tabControllers = [WindowController]()  // << storage for child controllers

    @IBAction override func newWindowForTab(_ sender: Any?) {
        if let wc = NSStoryboard.main?.instantiateInitialController() as? WindowController,
            let window = wc.window {
            self.window?.addTabbedWindow(window, ordered: .above)
            window.makeKey()

            tabControllers.append(wc) // keep reference in storage

            // TODO: - you are responsible to manage wc, eg: remove 
            // from storage on window close.
        }
    }
}