一.NSWindow
NSWindow
窗口是应用UI界面视图的容器,它负责接收用户的鼠标键盘等系统事件,转发消息到相关的接收者对象。AppKit提供的一些子类化的窗口还可以实现一些辅助交互功能,比如文件打开保存的对话框,字体颜色选择器等等。- 每个应用启动后至少会打开一个窗口。当你运行多个应用App时,屏幕上会有多个窗口界面。我们把当前用户正在工作的应用的窗口称为活动或激活的窗口,其他应用的窗口相应的称为非活动的窗口。活动窗口顶部的title bar部分的颜色是高亮灰色选中状态。
KeyWindow
可以接收输入事件(键盘,鼠标,触控板等外设)
的窗口对象称为ZkeyWindow
Z;
MainWindow
当前的活动窗口
也称为mainWindow
。一个时刻只能有一个keyWindow和一个mainWindow。**
二.窗口界面的组成
窗口对象包括titleBar, contentView内容视图, contentBorder底部边框区。titleBar上面包括控制按钮、标题,如下图所示。
三.模态窗口
有些特殊场景需要限制用户只能处理完当前的窗口的任务
,完成任务后关闭它才能继续操作其他的窗口,这种窗口称为模态窗口(Modal Window
)。
模态窗口分为两种
- 1.Modal Window
这种window比较霸道,当它启动后,此时只有这个window可以接收响应用户操作,无法切换到其他窗口操作,其他窗口也不能接收处理系统内部的各种事件。
使用NSApplication的runModal
方法来创建Modal window
@IBAction func showModalWindow(_ sender: NSButton) {
NSApplication.shared.runModal(for: modalWindow)
modalWindow.center()
}
使用stopModal方法来结束模态.如果用户直接点击了窗口顶部最左侧的关闭按钮,窗口关闭了,但是整个应用仍然处于模态,任何操作都无法得到响应.正确的做法是监听窗口关闭事件,增加结束模态的方法调用.
func applicationDidFinishLaunching(_ aNotification: Notification) {
// Insert code here to initialize your application
NotificationCenter.default.addObserver(self, selector:#selector(self.windowClose(_:)), name: NSWindow.willCloseNotification, object: nil)
}
@objc func windowClose(_ aNotification: Notification){
NSApplication.shared.stopModal()
}
- 2.Modal Session
比起Modal windows,Modal sessions方式创建的window稍微温和一些,允许响应快捷键和系统菜单,比如字体颜色选择这些panel面板.
@IBAction func showSessionsWindow(_ sender: NSButton) {
sessionCode = NSApplication.shared.beginModalSession(for: self.modalWindow)
}
结束Modal sessions窗口,使用sessionCode做为参数来关闭Modal sessions窗口.跟上面的模态处理一样需要注册窗口关闭事件来正常执行模态状态关闭.
@objc func windowClose(_ aNotification: Notification){
if let sessionCode = sessionCode {
NSApplication.shared.endModalSession(sessionCode)
self.sessionCode = nil
}
}
四.创建窗口
使用NSWindow类创建窗口对象,除了frame参数,还需要制定styleMask来确定窗口样式风格.
func createWindow() {
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
myWindow = NSWindow(contentRect:frame, styleMask:style, backing:.buffered, defer:false)
myWindow.title = "New Create Window"
//显示window
myWindow.makeKeyAndOrderFront(self);
//居中
myWindow.center()
}
1. styleMask:表示窗口风格的参数
- borderless:没有项部标题栏和控制按钮。
- titled: 有顶部标题栏边框。
- closable: 带有关闭按钮。
- miniaturizable:带有最小化按钮。
- resizable:带有恢复按钮。
- texturedBackground:带纹理背景窗口。
- uitTitlAndToobarar窗口的标题栏按钮区和窗口顶部的标题区融合为一体。
- fullScreen:全屏显示。
- fullSizeContentView:内容视图占据整个窗口大小。
- utilityWindow: NSPanel 类型的窗口。
- docModalWindow:模态文档,NSPanel 类型窗口。
- nonactivatingPanel:一种非活动主应用NSPanel类型窗口,点击这种面板不会导致主应用窗口从活动状态变为非活动状态.
- hudWindow: HUD黑色风格窗口,只有NSPanel类型窗口支持.
2. backing: 窗口绘制的缓存模式
- retained: 兼容老系统参数,基本很少用到.
- nonretained: 不缓存直接绘制.
- buffered: 缓存绘制.
五. 窗口通知
当窗口状态变化时候,系统会发出相关通知消息.下面是一些典型的窗口通知事件,更多通知事件请参考NSWindow类文件中的定义.
- NSWindowDidBecomeKeyNotification:窗口成为keyWindow
- NSWindowDidBecomeMainNotification:窗口成为mainWindow
- NSWindowDidMoveNotification:窗口移动
- NSWindowDidResignKeyNotification:窗口不再是keyWindow
- NSWindowDidResignMainNotification:窗口不再是mai nWindow
- NSWindowDidResizeNotification:窗口大小改变
- NSWindowWillCloseNotification:关闭窗口
- NSWindowDidMiniaturizeNotification:窗口最小化
六.窗口内容(ContentView)
open var contentView: NSView?
@available(OSX 10.10, *)
open var contentViewController: NSViewController?
1.可以使用自定义的NSView或NSViewController的view,添加到contentView
self.window.contentView?.addSubview(myView)
2.macOS 10.10系统及以上,创建一个NSViewController的子类,实例化后赋值给NSWindow的contentViewController.
self.window.contentViewController = myViewController
七.窗口的创建和管理
- 般情况下很少需要单独创建和管理窗口NSWindow对象.NSWindow的创建都是基于项目场景模版创建,或者通过NSWindowController创建管理的.
- 新建一个项目,工程中会自动生成的MainMenu.xib中会包含一个Window对象,这个Window是由AppDelegate管理的.
- 新建一个项目,勾选Create Document-Based Application,自动生成的Document.xib会包含一个Window对象,这个Window是由NSDocument文档类来管理的.
- 新建一个NSWindowCotrller的子类WindowContoller,勾选使用xib, 自动生成的WindowController.xib会包含一个Window对象.