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,可以组合多个值。

全部枚举值:

.borderless:无边框窗口(无标题栏、无关闭按钮等);

.titled:有标题栏窗口;

.closable:显示关闭按钮(红色按钮),仅在 .titled 存在时有效;

.miniaturizable:可最小化(黄色按钮),仅在 .titled 存在时有效;

.resizable:可调整大小(绿色按钮),仅在 .titled 存在时有效;

.fullSizeContentView:内容视图可延伸到标题栏区域;

.unifiedTitleAndToolbar:标题栏与工具栏合并为一体;

.texturedBackground:有纹理背景的窗口,已废弃,旧 macOS 风格(不要再用);

.utilityWindow:辅助工具窗口;

.docModalWindow:文档模态窗口;

.nonactivatingPanel:不激活主窗口的面板;

.hudWindow:黑色半透明 HUD 风格窗口;

.fullScreen:全屏模式。

可组合使用,例如:

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 等,详细层级请见文章《macOS NSWindow.Level层级》。

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

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

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

17、collectionBehavior:NSWindow.CollectionBehavior类型,控制窗口的行为,如是否全屏、是否参与 Exposé,详细层级请见文章《macOS NSWindow.CollectionBehavior行为》。

18、ignoresMouseEvents:Bool类型,是否忽略鼠标事件(点击穿透),如果为false,窗口会拦截鼠标点击,用户无法点击到下面的窗口/视图。

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类型,设置窗口位置和尺寸是否自动保存(比如记住上次打开的位置)。

28、frame:NSRect类型,设置窗口的位置和大小。

29、isMiniaturized:Bool类型,是否最小化。

30、isZoomed:Bool类型,是否已最大化(缩放)。

31、canBecomeKey:Bool类型,是否可以成为 key window(可重写)。

override var canBecomeKey: Bool {
    return true
}

32、canBecomeMain:Bool类型,是否可以成为 main window(可重写)。

33、preventsApplicationTerminationWhenModal:Bool类型,模态窗口是否阻止退出。

34、animationBehavior:NSWindow.AnimationBehavior类型,控制出现/隐藏动画方式。

35、aspectRatio:NSSize类型,固定宽高比(选填)。

36、resizeIncrements:NSSize类型,缩放步长(拖动缩放时)。

37、contentMinSize:NSSize类型,内容区最小尺寸。

38、contentMaxSize:NSSize类型,内容区最大尺寸。

39、firstResponder:NSResponder?类型,当前响应链中的第一响应者。

40、initialFirstResponder:NSView?类型,初始的第一响应者。

41、representedURL:URL?类型,表示的文档路径(用于显示小图标)。

42、miniwindowImage:NSImage?类型,最小化后 Dock 中显示的图标。

43、representedFilename:String类型,与文档相关的文件路径(与 URL 类似)。

44、sharingType:NSWindow.SharingType类型,屏幕共享时是否包含此窗口。

46、frameAutosaveName:获取窗口的自动保存名称。

常用方法

1、显示和隐藏

makeKeyAndOrderFront(_:):让窗口成为 key window(接收键盘事件)并显示到最前面;

orderFront(_:):把窗口移到前面,但不一定成为 key window;

orderBack(_:):把窗口移到所有窗口后面;

orderOut(_:):把窗口移出屏幕(隐藏);

close():关闭窗口(释放资源,如果没有强引用);

miniaturize(_:):最小化到 Dock;

deminiaturize(_:):从 Dock 恢复;

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

2、第一响应者/事件焦点

makeFirstResponder(_:):设置窗口的第一响应者(优先接收键盘事件的对象);

firstResponder:当前第一响应者对象(只读属性);

resignKey():让窗口放弃 key window 状态;

becomeKey():让窗口成为 key window。

3、事件处理

sendEvent(_:):发送事件到窗口的事件分发系统(你可以 override 来做事件拦截);

keyDown(with:):键盘按下事件;

keyUp(with:):键盘松开事件;

mouseDown(with:) / mouseUp(with:):鼠标按下/松开;

mouseMoved(with:):鼠标移动;

rightMouseDown(with:):右键按下;

scrollWheel(with:):滚轮事件。

4、窗口外观和行为

setFrame(_:display:):设置窗口的位置和大小;

setFrame(_:display:animate:):设置窗口位置和大小(可动画);

center():把窗口移动到屏幕中央;

setContentSize(_:):修改内容区域大小;

setFrameOrigin(_:):仅修改窗口左下角位置;

setFrameTopLeftPoint(_:):修改窗口左上角位置;

toggleFullScreen(_:):切换全屏模式。

5、屏幕与坐标系转换

convertPoint(fromScreen:):从屏幕坐标转换到窗口坐标;

convertPoint(toScreen:):从窗口坐标转换到屏幕坐标;

convertRect(fromScreen:):矩形坐标转换;

convertRect(toScreen:):矩形坐标转换。

convertToScreen(_:):将窗口的NSRect转换为屏幕的NSRect。

convertFromScreen(_:):将屏幕的NSRect转换为窗口的NSRect。

6、其他实用方法

setContentView(_:):设置窗口的内容视图;

contentView:获取或替换窗口内容视图;

title:窗口标题(属性);

setIsVisible(_:):控制窗口是否可见;

saveFrame(usingName:) / setFrameUsingName(_:):保存/恢复窗口位置和大小;

setLevel(_:):设置窗口层级(如 .screenSaver);

setOpaque(_:):设置是否不透明;

setBackgroundColor(_:):设置背景颜色;

disableCursorRects() / enableCursorRects():控制光标区域刷新(减少绘制开销);

invalidateCursorRects(for:):刷新某个视图的光标区域;

drag(_:at:offset:event:pasteboard:source:slideBack:):实现窗口内拖拽;

frameAutosaveName:获取窗口的自动保存名称;

toggleToolbarShown(_:):切换工具栏显示/隐藏。

基本用法

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

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()

相关文章

1、macOS NSWindow.Level层级:https://fangjunyu.com/2025/07/29/macos-nswindow-level%e5%b1%82%e7%ba%a7/

   

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

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

发表回复

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