Swift 如何从新创建的、以编程方式创建的选项卡的视图控制器与窗口控制器通信?
在我的窗口控制器中,我实现:Swift 如何从新创建的、以编程方式创建的选项卡的视图控制器与窗口控制器通信?,swift,xcode,macos,cocoa,Swift,Xcode,Macos,Cocoa,在我的窗口控制器中,我实现: @IBAction override func newWindowForTab(_ sender: Any?) { if let wc = NSStoryboard.main?.instantiateInitialController() as? WindowController, let window = wc.window { self.windo
@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
如果我没有任何标签,它就可以得到窗口控制器。但在新标签上,它确实抓住了窗口控制器
类似地,我尝试向WindowController发送操作失败:
NSApp.sendAction(#选择器(WindowController.pageLabelChange),to:nil,from:label)
适用于原始窗口,但不适用于任何新创建的选项卡
新创建的视图控制器对象如何与窗口控制器通信
编辑:
关于我如何使用这段代码的更多内容:它基本上是一个嵌入在窗口中的PDFView。该窗口有一个显示页码的工具栏。使用上面的任何代码,我都可以设置PDFView的当前页码,但是当有选项卡时,它就不起作用了。使用.PDFViewPageChanged
通知,我调用我的func
NSApp.sendAction(#selector(WindowController.pageLabelChange), to: nil, from: pdfView)
编辑2:
我已经创建了一个带有。您应该能够看到,启动项目时,
+
按钮将向选项卡栏中的文本字段添加一个数字。但如果您转到“视图”菜单>“添加”选项卡,它会创建一个新选项卡,但+
什么也不做。您在堆栈上创建了新的窗口控制器,因此它在返回后立即被销毁,这就是原因。您需要将对已创建选项卡窗口控制器的引用存储在某个位置并对其进行管理(存储位置取决于您的应用程序逻辑)
下面是一个简单的演示,可以让代码正常工作
使用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.
}
}
}
最终类WindowController:NSWindowController{
@IBOutlet弱var测试字段:NSTextField!
var tabControllers=[WindowController]()//您在堆栈上创建了新的窗口控制器,因此它在返回后立即被销毁,这就是原因。您需要将创建的选项卡窗口控制器的引用存储在某个地方并对其进行管理(存储位置取决于您的应用程序逻辑)
下面是一个简单的演示,可以让代码正常工作
使用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.
}
}
}
最终类WindowController:NSWindowController{
@IBOutlet弱var测试字段:NSTextField!
var tabControllers=[WindowController]()//谢谢。这种内存管理一直是学习Swift最困难的部分。这解决了我的问题,但是为什么windowcontroller在创建后马上就被销毁了?我知道没有对它的强烈引用,但窗口在屏幕上。@TomJ,window和window controller是不同的对象,对window的引用可以保存在其他位置-父窗口、应用程序等。@TomJNSApplication
在窗口关闭之前保留对窗口的强引用。未来读者注意:将tabControllers
存储在全局位置,不要将其作为窗口控制器的属性。谢谢。这种内存管理一直是最困难的部分这就解决了我的问题,但是为什么windowcontroller在创建后马上就被销毁了?我知道这里没有对它的强烈引用,但窗口在屏幕上。@TomJ、窗口和窗口控制器是不同的对象,对窗口的引用可以保留在其他地方-父窗口、应用程序等。@TomJNS应用程序
在窗口关闭之前保留对其的强引用。请注意:将选项卡控制器
存储在全局位置,不要将其作为窗口控制器的属性。