如何从以编程方式新创建的选项卡的视图控制器与 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.
}
}
}
在我的 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.
}
}
}