如何在 Swift 中使用 Cocoa 在 macOS 中打开另一个 window
How do I open another window in macOS in Swift with Cocoa
我正在开发一个在 table 视图中显示客户主记录列表的 macOS 应用程序。双击 table 视图中的一行应该会打开一个新的 window,用户可以在其中查看和编辑客户信息。
这是一个 Xcode 8.3.3 项目,使用故事板和 Swift。
它不是文档或核心数据应用程序。
我让主要 window 工作到 table 视图正确显示记录并且关联的视图控制器正在接收双击事件并将它们记录到控制台的地步.
我已经为编辑创建了一个额外的 window 控制器和视图 window 并通过暂时将其标记为初始控制器来验证其基本功能。
我无法弄清楚的是如何在用户双击一行时显示 window 的新实例。
感谢@Joshua Nozzi,我更接近了。这是此时的代码。
let storyboard = NSStoryboard(name: "Main", bundle: nil)
if let windowController = storyboard.instantiateController(withIdentifier: "xyzzy") as? NSWindowController
{
windowController.showWindow(self)
}
它正在生成
(Storyboard: 0x620000000680) doesn't contain a controller with
identifier 'xyzzy'
错误。
Window Programming Guide 是了解 windows 一般管理方式的好地方。
具体来说(假设您知道如何在故事板中呈现 window 控制器场景),您需要在某处存储对新 window 控制器的引用,这样它们就不会立即被释放(并消失) ) 呈现时。
在您的情况下,您可能希望在主 window 控制器中保留一组公开细节 windows,这样如果主控制器离开,细节也会消失。当细节 window 打开时(创建控制器实例并显示其 window ),您会将其控制器存储在数组中;当关闭时,你从数组中移除它的控制器,这样它就被释放了。
有多种方法可以做到这一点,具体取决于您想要多少控制权、您希望子 window 所有权如何运作等,但这种基本模式通常就足够了。
要从情节提要中实例化新的 window 控制器场景:
var myWindowController = NSStoryboard(name: "MyStoryboardFileName", bundle: nil)?.instantiateControllerWithIdentifier("MyWindowControllerIdentifier") as MyWindowControllerClass
myWindowController?.showWindow(self)
确认。这是 UI 中的一个主要陷阱。启动时有问题:
解决这个问题浪费了一整天时间。
此外,要打开新的 window,此代码可以帮助您
windowController.contentViewController = tabViewController
完整代码就像我在项目中使用的那样:
@objc func openApplicationView(_ sender: Any?) {
let mainStoryBoard = NSStoryboard(name: "Main", bundle: nil)
let tabViewController = mainStoryBoard.instantiateController(withIdentifier: "tabView") as? TabViewController
let windowController = mainStoryBoard.instantiateController(withIdentifier: "secondWindow") as! TabViewWindowController
windowController.showWindow(self)
windowController.contentViewController = tabViewController
}
如果您关闭了 mainWindow,它会有所帮助。所以你需要在你自己的底层故事板中添加一个 windowController 和 tabViewController(你可以使用普通视图控制器)。
在我这边,tabViewController 已由 NSTabViewController 扩展,选项卡视图组件已与此 class.
绑定
注意:我还在我的 Main.storyboard 中添加了 windowController 作为一个组件,并确定要在编码端使用。
我正在开发一个在 table 视图中显示客户主记录列表的 macOS 应用程序。双击 table 视图中的一行应该会打开一个新的 window,用户可以在其中查看和编辑客户信息。
这是一个 Xcode 8.3.3 项目,使用故事板和 Swift。
它不是文档或核心数据应用程序。
我让主要 window 工作到 table 视图正确显示记录并且关联的视图控制器正在接收双击事件并将它们记录到控制台的地步.
我已经为编辑创建了一个额外的 window 控制器和视图 window 并通过暂时将其标记为初始控制器来验证其基本功能。
我无法弄清楚的是如何在用户双击一行时显示 window 的新实例。
感谢@Joshua Nozzi,我更接近了。这是此时的代码。
let storyboard = NSStoryboard(name: "Main", bundle: nil)
if let windowController = storyboard.instantiateController(withIdentifier: "xyzzy") as? NSWindowController
{
windowController.showWindow(self)
}
它正在生成
(Storyboard: 0x620000000680) doesn't contain a controller with identifier 'xyzzy'
错误。
Window Programming Guide 是了解 windows 一般管理方式的好地方。
具体来说(假设您知道如何在故事板中呈现 window 控制器场景),您需要在某处存储对新 window 控制器的引用,这样它们就不会立即被释放(并消失) ) 呈现时。
在您的情况下,您可能希望在主 window 控制器中保留一组公开细节 windows,这样如果主控制器离开,细节也会消失。当细节 window 打开时(创建控制器实例并显示其 window ),您会将其控制器存储在数组中;当关闭时,你从数组中移除它的控制器,这样它就被释放了。
有多种方法可以做到这一点,具体取决于您想要多少控制权、您希望子 window 所有权如何运作等,但这种基本模式通常就足够了。
要从情节提要中实例化新的 window 控制器场景:
var myWindowController = NSStoryboard(name: "MyStoryboardFileName", bundle: nil)?.instantiateControllerWithIdentifier("MyWindowControllerIdentifier") as MyWindowControllerClass
myWindowController?.showWindow(self)
确认。这是 UI 中的一个主要陷阱。启动时有问题:
此外,要打开新的 window,此代码可以帮助您
windowController.contentViewController = tabViewController
完整代码就像我在项目中使用的那样:
@objc func openApplicationView(_ sender: Any?) {
let mainStoryBoard = NSStoryboard(name: "Main", bundle: nil)
let tabViewController = mainStoryBoard.instantiateController(withIdentifier: "tabView") as? TabViewController
let windowController = mainStoryBoard.instantiateController(withIdentifier: "secondWindow") as! TabViewWindowController
windowController.showWindow(self)
windowController.contentViewController = tabViewController
}
如果您关闭了 mainWindow,它会有所帮助。所以你需要在你自己的底层故事板中添加一个 windowController 和 tabViewController(你可以使用普通视图控制器)。
在我这边,tabViewController 已由 NSTabViewController 扩展,选项卡视图组件已与此 class.
绑定注意:我还在我的 Main.storyboard 中添加了 windowController 作为一个组件,并确定要在编码端使用。