NSWindowController (窗口控制器)

2020-05-13  本文已影响0人  zhongxiaoyue

NSWindowController


加载过程

1. 使用Xib

2. 使用Storyboard

关闭过程


NSWindowDelegate

常用代理

// 窗口大小将要变更
func windowWillResize(NSWindow, to: NSSize) -> NSSize
// 窗口大小已经变更
func windowDidResize(Notification)
// 窗口将要最小化
func windowWillMiniaturize(Notification)
// 窗口已经最小化
func windowDidMiniaturize(Notification)
// 窗口即将进入全屏模式
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
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的释放,系统是特殊处理,只要关闭就释放了.

  1. 使用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 ControllerView Controller Scene不同的分层的场景,这种架构划分是非常合理的。所以推荐使用Storyboard来完成工程创建.
上一篇下一篇

猜你喜欢

热点阅读