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
}
}
我是初学者 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
}
}