Swift 中没有 nib 文件的 NSWindowController

NSWindowController without a nib file in Swift

我是初学者 Cocoa 开发人员。我受雇的团队在 Swift 中进行 OS X 开发而不使用 nib 文件(显然主菜单除外)。所以,我想在加入团队之前学习这一点。这是我目前所拥有的:

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

在MainMenu.xib文件中,我删除了应用默认自带的window,但保留了主菜单。

在应用委托中,我删除了 window 的默认插座。

然后我在应用程序委托中以编程方式创建了一个 NSWindow。我希望 MainWindowController 成为此 window 的委托。这是我的 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
    }

}

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

然后,在我的自定义 NSWindowController 中,我使用 'self.window?.delegate = self' 使 'self' 成为 window 的委托。这是我的 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")
    } 
}

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

当我 运行 应用程序时,window 会显示。但是,当我最小化或关闭 window 时,控制台不会打印任何内容。因此,似乎没有为 window.

正确设置委托

正确的做事方式是什么?

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

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

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)
    }
}

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

import Cocoa

@main
class AppDelegate: NSObject, NSApplicationDelegate {

    let windowController = MainWindowController(
        window: NSWindow(contentRect: NSMakeRect(100, 100, NSScreen.main!.frame.width/2, NSScreen.main!.frame.height/2),
        styleMask: .defaultWindow,
        backing: .buffered,
        defer: false))

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

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

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.
    }

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

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

extension NSWindow.StyleMask {
    static var defaultWindow: NSWindow.StyleMask {
        var styleMask: NSWindow.StyleMask = .closable
        styleMask.formUnion(.titled)
        styleMask.formUnion(.resizable)
        styleMask.formUnion(.miniaturizable)
        return styleMask
    }
}