一.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對象.