macOS窗口NSWindow
macOS窗口NSWindow

macOS窗口NSWindow

NSWindow 是 macOS(AppKit)中的核心类,用于表示屏幕上的一个窗口,例如在 Finder、Safari 或 Xcode 中看到的每一个窗口,其实背后都是 NSWindow 实例在工作。

初始化方法

NSWindow(
    contentRect: NSRect,
    styleMask: NSWindow.StyleMask,
    backing: NSWindow.BackingStoreType,
    defer: Bool
)

这个是 NSWindow 的最常用构造方法,四个参数如下:

1、contentRect: NSRect

说明:窗口的初始尺寸和位置(相对于屏幕左下角)。

类型:NSRect,通常用 NSRect(x: y: width: height:) 创建。

注意:这是内容区域大小(不包括标题栏),窗口框架会根据 styleMask 自动扩展。

contentRect: NSRect(x: 100, y: 100, width: 600, height: 400)

2、styleMask: NSWindow.StyleMask

说明:指定窗口的样式,如是否可关闭、可调整大小、有标题栏等。

类型:NSWindow.StyleMask,可以组合多个值。

常用枚举值:

.titled:带标题栏。

.closable:可关闭。

.miniaturizable:可最小化。

.resizable:可调整大小。

.fullSizeContentView:内容扩展到整个窗口,包括标题栏区域。

.borderless:无边框窗口(用于自定义外观)。

可组合使用,例如:

styleMask: [.titled, .closable, .resizable]

3、backing: NSWindow.BackingStoreType

说明:决定窗口如何缓存绘图内容。现在基本固定为 .buffered。

类型:NSWindow.BackingStoreType

常用值:

.buffered(推荐,默认值):所有绘图操作在内存中完成,macOS 推荐的方式。

其他值(如 .retained)已废弃,不推荐使用。

backing: .buffered

4、defer: Bool

说明:是否推迟窗口的屏幕分配(窗口 frame 是否立即与屏幕绑定)。

类型:Bool

推荐值:

false:立即分配(大多数场景下使用)

true:延迟分配(如果之后会修改 frame)

defer: false

5、完整示例

let window = NSWindow(
    contentRect: NSRect(x: 200, y: 200, width: 400, height: 300),
    styleMask: [.titled, .closable, .resizable],
    backing: .buffered,
    defer: false
)
window.title = "My Custom Window"
window.center()
window.makeKeyAndOrderFront(nil)

通过初始化NSWindow和属性,完成NSWindow窗口的创建。

常用属性

1、contentView:NSView?类型,主内容视图,用来显示自定义的 UI(通常是由 NSViewController 提供的 view)。

2、contentViewController:NSViewController?类型,用于控制器绑定(推荐使用)。

3、title:String类型,窗口标题,显示在标题栏上。

4、styleMask:NSWindow.StyleMask类型,决定窗口样式,如是否可移动、是否有标题栏、是否全屏等。

5、isVisible:Bool类型,表示是否正在显示。

6、isKeyWindow:Bool类型,表示当前是否为「主窗口」(接收键盘事件)。

7、isMainWindow:Bool类型,表示当前是否为「前台窗口」(应用激活时显示的窗口)。

8、windowController:NSWindowController?类型,负责控制该窗口的控制器(如果有)。

9、toolbar:NSToolbar?类型,工具栏(可选)。

10、backgroundColor:NSColor类型,设置窗口背景颜色。

11、hasShadow:Bool类型,是否启用窗口阴影(默认为true)。

12、isReleasedWhenClosed:Bool类型,关闭窗口时是否释放(SwiftUI中应设为false)。

13、level:NSWindow.Level类型,控制窗口层级,例如浮动窗口 .floating、主窗口 .normal 等。

14、isMovable:Bool类型,是否允许用户移动窗口(默认 true)。

15、minSize / maxSize:NSSize类型,限制窗口最小和最大尺寸。

16、alphaValue:CGFloat类型,控制窗口透明度(0.0 到 1.0)。

17、collectionBehavior:NSWindow.CollectionBehavior类型,控制窗口的行为,如是否全屏、是否参与 Exposé。

18、ignoresMouseEvents:Bool类型,是否忽略鼠标事件(点击穿透)。

19、canHide:Bool类型,窗口是否可以被隐藏。

20、hidesOnDeactivate:Bool类型,应用失去焦点时是否自动隐藏窗口。

21、standardWindowButton(_:),NSButton?类型,获取关闭、最小化、缩放按钮(可自定义位置或隐藏)。

22、isMovableByWindowBackground,Bool类型,用户是否可以通过拖拽窗口背景区域(非标题栏部分)来移动窗口。

23、titlebarAppearsTransparent:Bool类型,是否让标题栏背景透明,使内容区域可以延伸到标题栏(现代风格的核心)。

24、titleVisibility:NSWindow.TitleVisibility类型,控制窗口标题文字是否显示(.visible, .hidden)。

25、toolbarStyle:NSWindow.ToolbarStyle类型,工具栏样式,决定工具栏和标题栏是否融合(.automatic, .expanded, .preference, .unified, .unifiedCompact)。

26、isOpaque:Bool类型,是否完全不透明(通常配合透明背景时设置为 false)。

27、setFrameAutosaveName(_:):String类型,设置窗口位置和尺寸是否自动保存(比如记住上次打开的位置)。

常用方法

1、makeKeyAndOrderFront(_:):显示窗口并置为主窗口(常用于打开窗口)。

2、orderOut(_:):隐藏窗口。

3、close():关闭窗口(销毁)。

4、zoom(_:):最大化或恢复窗口大小。

5、miniaturize(_:):最小化窗口。

6、toggleFullScreen(_:):切换全屏。

7、setFrame(_:display:animate:):手动设置窗口位置和大小。

8、center():窗口居中。

基本用法

创建一个简单的窗口并显示内容。

class MyViewController: NSViewController {
    override func loadView() {
        self.view = NSView()
        self.view.wantsLayer = true
        self.view.layer?.backgroundColor = NSColor.systemTeal.cgColor
        self.view.setFrameSize(NSSize(width: 400, height: 300))
    }
}

let vc = MyViewController()

let window = NSWindow(
    contentRect: NSRect(x: 0, y: 0, width: 400, height: 300),
    styleMask: [.titled, .closable, .resizable],
    backing: .buffered,
    defer: false
)
window.center()
window.title = "Hello Window"
window.contentViewController = vc
window.makeKeyAndOrderFront(nil)

在该代码中,使用MyViewController创建NSView视图和NSViewController视图控制器。

初始化NSWindow,将NSWindow窗口居中,标题为Hello Window,内容视图控制器为MyViewController,并将创建好的NSWindow设置为主窗口。

搭配NSWindowController

通常使用NSWindowController管理NSWindow,例如:

class MyWindowController: NSWindowController {
    convenience init() {
        let vc = MyViewController()
        let window = NSWindow(
            contentRect: NSRect(x: 0, y: 0, width: 400, height: 300),
            styleMask: [.titled, .closable, .resizable],
            backing: .buffered,
            defer: false
        )
        window.contentViewController = vc
        self.init(window: window)
    }
}

使用场景

1、显示主窗口、设置窗口、弹出窗口。

2、自定义窗口样式,如无边框播放器窗口。

3、多窗口应用,如 Xcode 工程窗口、调试窗口。

4、弹出临时视图或辅助工具视图。

总结

通过初始化NSWindow可以实现窗口的创建,NSWindow通常配合NSWindowController。

如果想要在NSWindow中显示SwiftUI视图,可以使用NSHostingController配合显示视图:

let hosting = NSHostingController(rootView: SettingsView())
let window = NSWindow(
    contentRect: NSRect(x: 0, y: 0, width: 300, height: 200),
    styleMask: [.titled, .closable, . resizable],
    backing: .buffered,
    defer: false
)
window.contentViewController = hosting
window.title = "设置"
window.center()
   

如果您认为这篇文章给您带来了帮助,您可以在此通过支付宝或者微信打赏网站开发者。

欢迎加入我们的 微信交流群QQ交流群,交流更多精彩内容!
微信交流群二维码 QQ交流群二维码

发表回复

您的电子邮箱地址不会被公开。 必填项已用 * 标注