我有一个显示表的NSWindowController
,并使用另一个控制器作为NSTableView
的数据源和委托。第二个控制器显示来自对象的信息,该信息由NSWindowController
传入。该控制器依次将对象设置为AppDelegate
的属性。它看起来像这样:
class SomeWindowController: NSWindowController {
var relevantThing: Thing!
var someTableController: SomeTableController!
@IBOutlet weak var someTable: NSTableView!
override func windowDidLoad() {
someTableController = SomeTableController(thing: relevantThing)
someTable.dataSource = someTableController
someTable.delegate = someTableController
}
}
在AppDelegate
我然后做
func applicationDidFinishLaunching(_ aNotification: Notification) {
relevantThing = Thing()
someWindowController = SomeWindowController()
someWindowController.relevantThing = relevantThing
someWindowController.showWindow(nil)
}
这是一种合理的方法吗?我觉得SomeWindowController
中使用的隐式解包选项可能是不好的形式。此外,relevantThing
不允许在我的情况下更改,因此我觉得let
会更正确。也许relevantThing
应该保持不变并通过初始化器传入?或者会破坏init?(coder: NSCoder)
初始化程序?
我非常感谢任何建议,因为我试图了解在Swift中做正确事情的正确方法。
答案 0 :(得分:0)
一些事情:
您是否有任何理由在代码中创建窗口控制器而不是从storyboard / xib加载它?
通常,更好的做法是将所有“控制器”放在一起。这与NSViewController
中的视图相关,仅使用NSWindowController
与窗口本身相关的内容(例如工具栏,窗口管理等)。
与iOS类似,NSViewController
现已集成到窗口/视图生命周期和响应程序链中。对于许多窗口,您甚至不需要继承NSWindowController
。
XCode的应用程序项目模板使用窗口,主视图及其控制器创建故事板。这是一个很好的起点。
NSWindowController
具有contentViewController
属性,该属性设置为主内容视图的NSViewController
(从故事板加载时)。您通常不需要视图控制器的单独视图控制器属性。
我认为通常,您希望最大限度地减少从外部代码修改控制器并使其尽可能独立。这使它们更易于测试和重复使用。
如果您的Thing
实例对于整个应用程序是全局的(从代码中显示),您可能需要考虑将其作为单例实例添加到Thing
类并从中检索它NSViewController
(例如在viewDidLoad()
)
如果您将控制器/视图放在故事板中,则可以在此处连接表的数据源/委托。如果这是您的主窗口,它可以加载并在应用程序启动时自动显示。但无论如何,请将NSViewController
/ View布线放在视图控制器中。
如果要将主NSViewController之间的逻辑分离为处理视图特定部分的更专业的视图控制器,可以在Interface Builder中使用NSContainerView
添加其他视图控制器来处理特定视图。 / p>