美文网首页
NSWindowController (窗口控制器)

NSWindowController (窗口控制器)

作者: zhongxiaoyue | 来源:发表于2020-05-13 18:01 被阅读0次

    NSWindowController

    • NSWindowController是用来管理window的控制器,能够管理xibstoryboard文件中加载的窗口视图。在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:等价执行了orderFrontmakeKey

    关闭过程

    • 1). 执行NSWindow的close方法
    • 2). 执行orderOut方法

    NSWindowDelegate

    常用代理

      1. 调整Windows大小
    // 窗口大小将要变更
    func windowWillResize(NSWindow, to: NSSize) -> NSSize
    // 窗口大小已经变更
    func windowDidResize(Notification)
    
      1. 最小化Windows
    // 窗口将要最小化
    func windowWillMiniaturize(Notification)
    // 窗口已经最小化
    func windowDidMiniaturize(Notification)
    
      1. 全屏Windows
    // 窗口即将进入全屏模式
    func windowWillEnterFullScreen(Notification)
    // 窗口已进入全屏模式
    func windowDidEnterFullScreen(Notification)
    // 窗口即将退出全屏模式
    func windowWillExitFullScreen(Notification)
    // 窗口已退出全屏模式
    func windowDidExitFullScreen(Notification)
    
      1. 窗口移动
    // 窗口将要移动
    func windowWillMove(Notification)
    // 窗口已移动
    func windowDidMove(Notification)
    
      1. 关闭窗口
    // 用户试图关闭窗口,return 是否允许关闭
    func windowShouldClose(NSWindow) -> Bool
    // 窗口即将关闭
    func windowWillClose(Notification)
    
      1. 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的释放,系统是特殊处理,只要关闭就释放了.

    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来完成工程创建.

    相关文章

      网友评论

          本文标题:NSWindowController (窗口控制器)

          本文链接:https://www.haomeiwen.com/subject/nytinhtx.html