NSWindowController (窗口控制器)
2020-05-13 本文已影响0人
zhongxiaoyue
NSWindowController
-
NSWindowController
是用来管理window
的控制器,能够管理xib
或storyboard
文件中加载的窗口视图。在Document-Based应用中,NSWindowController也负责创建和管理document的window
。 - NSWindowController在基于UI界面的应用中,管理不同场景多个界面窗口的切换,可以说起了非常重要的作用。
- 创建基于xib的一个NSWindowController类后就自动完成了NSWindow的创建,因此一般情况下很少单独去创建一个独立的NSWindow,只需要调用NSWindowController的
showWindow
方法显示window就可以了。
加载过程
1. 使用Xib
- 1).
LoadNib
: NSApplication运行后加载xib文件 - 2).
orderFront
:创建window对象显示window - 3).
makeKey
:app启动完成后,使当前window成为keyWindow
2. 使用Storyboard
- 1).
LoadNib
: NSApplication运行后加载Storyboard文件 - 2).
makeKeyAndOrderFront
:等价执行了orderFront
和makeKey
关闭过程
- 1). 执行NSWindow的
close
方法 - 2). 执行
orderOut
方法
NSWindowDelegate
常用代理
- 调整Windows大小
// 窗口大小将要变更
func windowWillResize(NSWindow, to: NSSize) -> NSSize
// 窗口大小已经变更
func windowDidResize(Notification)
- 最小化Windows
// 窗口将要最小化
func windowWillMiniaturize(Notification)
// 窗口已经最小化
func windowDidMiniaturize(Notification)
- 全屏Windows
// 窗口即将进入全屏模式
func windowWillEnterFullScreen(Notification)
// 窗口已进入全屏模式
func windowDidEnterFullScreen(Notification)
// 窗口即将退出全屏模式
func windowWillExitFullScreen(Notification)
// 窗口已退出全屏模式
func windowDidExitFullScreen(Notification)
- 窗口移动
// 窗口将要移动
func windowWillMove(Notification)
// 窗口已移动
func windowDidMove(Notification)
- 关闭窗口
// 用户试图关闭窗口,return 是否允许关闭
func windowShouldClose(NSWindow) -> Bool
// 窗口即将关闭
func windowWillClose(Notification)
- KeyWindow (接收键盘鼠标事件的窗口)
// 窗口已成为KeyWindow
func windowDidBecomeKey(Notification)
// 窗口已退出KeyWindow状态
func windowDidResignKey(Notification)
常见问题
1.实现懒加载的属性方法
lazy var myWindow = { () -> NSWindow in
let frame = CGRect(x: 0, y: 0, width: 400, height: 280)
let style : NSWindow.StyleMask = [NSWindow.StyleMask.titled,NSWindow.StyleMask.closable,NSWindow.StyleMask.resizable]
//创建window
let myWindow = NSWindow(contentRect:frame, styleMask:style, backing:.buffered, defer:false)
myWindow.title = "New Create Window"
return NSWindow.init()
}()
2.定义按钮的点击事件,显示myWindow
func showWindowAction(_ sender: NSButton) {
self.myWindow.makeKeyAndOrderFront(self)
}
你会发现只有第一次你可以正常的呼出myWindow显示到屏幕上,当你关闭这个window。再次点击button时程序crash了!
这是因为我们虽然强引用了myWindow,但是对于window的释放,系统是特殊处理,只要关闭就释放了.
- 使用NSWindowController管理Window
lazy var myWindowController = { () -> NSWindowController in
let myWindowController = NSWindowController.init()
self.myWindow.windowController = myWindowController
myWindowController.window = self.myWindow
return myWindowController
}()
这样重新运行App,反复关闭window在点击button打开,没有crash,一切很正常。
这样我们可以得出一个结论:手工创建的NSWindow,关闭后系统会检查这个window有没有
controller引用它,有的话就不会释放这个window对象。xib中创建的window则没有这个问题。
AppDelegate中Window管理分离
新建一个NSWindowArchitecture项目工程
MainMenu.xib中默认生成一个Window,这个Window是由AppDelegate负责管理的,从应用的单一职责划分的原则考虑,Window适合由独立的NSWindowController去管理。
删除点击Window对象
新建一个文件AppMainWindowController,继承NSWindowController,勾选使用xib修改AppMainWindowController中默认的代码,增加窗口居中显示,返回window的xib文件名。
class AppMainWindowController: NSWindowController {
override func windowDidLoad() {
super.windowDidLoad()
// Implement this method to handle any initialization after your window controller's window has been loaded from its nib file.
window?.center()
}
override var windowNibName: NSNib.Name? {
get{
return NSNib.Name(rawValue: "AppMainWindowController")
}
}
}
AppDelegate中增加AppMainWindowController的相关代码
class AppDelegate: NSObject, NSApplicationDelegate {
lazy var windowController: AppMainWindowController = {
let wondowVC = AppMainWindowController()
return wondowVC
}()
func applicationDidFinishLaunching(_ aNotification: Notification) {
self.windowController.showWindow(self)
}
}
直接使用xib创建的工程和分离window调整后的架构对比,可以看出架构2在扩展和维护性方面都代于架构1
如果我们创建工程的时候勾选是使用Storyboard选项,系统会创建Window Controller和View Controller Scene不同的分层的场景,这种架构划分是非常合理的。所以推荐使用Storyboard来完成工程创建.