You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

SwiftUI:macOS应用启动时打开多个窗口

macOS SwiftUI 启动时自动打开多窗口的实现方案

在SwiftUI中,直接添加多个WindowGroup确实只会默认启动第一个,要实现启动时打开两个分别在不同屏幕的窗口,需要通过NSApplicationDelegateAdaptor配合AppKit的窗口API手动创建和配置窗口,具体实现如下:

实现思路

通过自定义NSApplicationDelegate子类,在应用启动完成的回调里手动创建两个窗口,并分别指定它们的显示屏幕;最后在SwiftUI的App结构体中注册这个自定义Delegate,替代默认的窗口启动逻辑。

完整代码示例

import SwiftUI
import AppKit

// 自定义AppDelegate,负责创建并配置双窗口
class AppDelegate: NSObject, NSApplicationDelegate {
    func applicationDidFinishLaunching(_ notification: Notification) {
        let screens = NSScreen.screens
        
        // 1. 创建副屏窗口(如果存在多屏幕)
        if screens.count > 1 {
            let secondaryScreen = screens[1]
            let secondaryWindow = NSWindow(
                contentRect: secondaryScreen.frame,
                styleMask: [.titled, .closable, .resizable],
                backing: .buffered,
                defer: false
            )
            secondaryWindow.title = "Test"
            secondaryWindow.contentView = NSHostingView(rootView: 
                Text("Hello test")
                    .frame(width: 1000, height: 1000, alignment: .center)
            )
            secondaryWindow.setFrame(secondaryScreen.frame, display: true)
            secondaryWindow.makeKeyAndOrderFront(nil)
        }
        
        // 2. 创建主屏控制窗口
        let mainScreen = screens[0]
        let mainWindow = NSWindow(
            contentRect: NSRect(
                x: mainScreen.frame.midX - 400, 
                y: mainScreen.frame.midY - 500, 
                width: 800, 
                height: 1000
            ),
            styleMask: [.titled, .closable, .resizable],
            backing: .buffered,
            defer: false
        )
        mainWindow.title = "Control Window"
        mainWindow.contentView = NSHostingView(rootView: 
            ContentView()
                .frame(minWidth: 800, minHeight: 1000)
        )
        mainWindow.center()
        mainWindow.makeKeyAndOrderFront(nil)
    }
}

@main
struct MyApp: App {
    // 注册自定义AppDelegate
    @NSApplicationDelegateAdaptor(AppDelegate.self) var appDelegate
    
    // 保留空WindowGroup并隐藏,避免SwiftUI自动生成空白窗口
    var body: some Scene {
        WindowGroup {
            EmptyView()
        }
        .hidden()
    }
}

代码说明

  • NSScreen.screens获取系统所有屏幕,索引0对应主屏,索引1对应副屏(屏幕顺序可根据系统设置调整)
  • 用NSWindow手动创建窗口,通过NSHostingView将SwiftUI视图作为窗口内容载体
  • setFrame指定窗口在目标屏幕的显示位置,makeKeyAndOrderFront触发窗口显示
  • 隐藏默认WindowGroup是为了避免SwiftUI自动生成多余的空白窗口

这样应用启动时就会自动在主屏和副屏分别打开控制窗口和内容窗口。

内容的提问来源于stack exchange,提问作者pipo92

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.26 03:48:23