在Swift中没有nib文件的NSWindowController

时间:2015-12-30 22:16:24

标签: swift nswindowcontroller

我是初学Cocoa开发人员。我被聘用的团队在Swift中进行OS X开发而不使用nib文件(显然主菜单除外)。所以,在我加入团队之前,我正在努力学习这一点。以下是我到目前为止的情况:

我创建了一个没有故事板的新OS X项目。我创建了一个名为MainWindowController.swift的新文件,使其成为NSWindowController的子类,并且没有创建xib / nib文件。我还使MainWindowController实现了NSWindowDelegate协议

在MainMenu.xib文件中,我默认删除了应用程序附带的窗口,但我保留了主菜单。

在app delegate中,我删除了窗口的默认插座。

然后我在app delegate中以编程方式创建了一个NSWindow。我希望MainWindowController成为这个窗口的委托。这就是我的AppDelegate的样子:

import Cocoa

@NSApplicationMain
class AppDelegate: NSObject, NSApplicationDelegate {

    let newWindow = NSWindow(contentRect: NSMakeRect(100, 100, NSScreen.mainScreen()!.frame.width/2, NSScreen.mainScreen()!.frame.height/2), styleMask: NSTitledWindowMask|NSResizableWindowMask|NSMiniaturizableWindowMask|NSClosableWindowMask, backing: NSBackingStoreType.Buffered, `defer`: false)

    func applicationDidFinishLaunching(aNotification: NSNotification) {
        // Insert code here to initialize your application
        let wc = MainWindowController.init(window: newWindow)
        wc.showWindow(self)
    }

    func applicationWillTerminate(aNotification: NSNotification) {
        // Insert code here to tear down your application
    }

}

正如您所看到的,我正在创建一个窗口对象,然后在applicationDidFinishLaunching方法中,我使用该窗口初始化我的自定义NSWindowController,然后显示该窗口。我不确定这是否正确。

然后,在我的自定义NSWindowController中,我正在制作自己的'窗口的代表使用' self.window?.delegate = self'。这就是我的MainWindowController的外观

import Cocoa

class MainWindowController: NSWindowController, NSWindowDelegate {

    override func windowDidLoad() {
        super.windowDidLoad()

        self.window?.delegate = self

        // Implement this method to handle any initialization after your window controller's window has been loaded from its nib file.

    }

    func windowDidMiniaturize(notification: NSNotification) {
        print("Window minimized")
    }

    func windowWillClose(notification: NSNotification) {
        print("Window closing")
    } 
}

如您所见,我在委托方法中有几个测试打印。

当我运行应用程序时,窗口会显示。但是,当我最小化或关闭窗口时,没有任何内容被打印到控制台。因此,似乎没有为窗口正确设置委托。

做事的正确方法是什么?

2 个答案:

答案 0 :(得分:5)

AppDelegate课程中,您不想将窗口存储在属性中,而是要存储窗口控制器。你现在拥有它的方式,没有对窗口控制器的强引用,因此在applicationDidFinishLaunching完成执行时会被销毁。窗口控制器将保持对其窗口的强引用,因此您不需要对窗口保持单独的强引用。我也会在applicationDidFinishLaunching中设置窗口的委托 - 我不确定当你不使用笔尖时是否调用了windowDidLoad

我认为你的AppDelegate课应该是这样的:

class AppDelegate: NSObject, NSApplicationDelegate {

    let windowController = MainWindowController(
        window: NSWindow(contentRect: NSMakeRect(100, 100, NSScreen.mainScreen()!.frame.width/2, NSScreen.mainScreen()!.frame.height/2), 
        styleMask: NSTitledWindowMask|NSResizableWindowMask|NSMiniaturizableWindowMask|NSClosableWindowMask, 
        backing: NSBackingStoreType.Buffered, 
       `defer`: false))

    func applicationDidFinishLaunching(aNotification: NSNotification) {
        // Insert code here to initialize your application
        windowController.window?.delegate = windowController
        windowController.showWindow(self)
    }
}

答案 1 :(得分:0)

这是 Aaron 答案(Xcode 12.4., Swift 5.3.)的稍微更新和更清晰的版本:

RewriteRule