SwiftUI:在 macOS 上关闭打开 window 会导致崩溃

SwiftUI: Closing opened window on macOS causes crash

我可以打开一个新的 window,但是如果我使用 window 的关闭按钮关闭它,我的应用程序就会崩溃。

import SwiftUI

struct ContentView: View
{
    var body: some View
    {
        Button(action: {openMyWindow()},
               label: {Image(systemName: "paperplane")})
            .padding()
    }
}

func openMyWindow()
{
    var windowRef:NSWindow
    windowRef = NSWindow(
        contentRect: NSRect(x: 100, y: 100, width: 100, height: 600),
        styleMask: [.titled, .closable, .miniaturizable, .resizable, .fullSizeContentView],
        backing: .buffered, defer: false)
    windowRef.contentView = NSHostingView(rootView: WindowView())
    windowRef.makeKeyAndOrderFront(nil)
}

struct WindowView: View
{
    var body: some View
    {
        Text("Hello World")
            .padding()
    }
}

@main

struct Open_WindowApp: App 
{
    var body: some Scene 
    {
        WindowGroup 
        {
            ContentView()
        }
    }
}

我想我需要保持我的 windowRef 活跃,但我该怎么做?

我们需要参考 window,尝试以下方法

struct ContentView: View
{
    @State private var windowRef: NSWindow?

    var body: some View
    {
        Button(action: {openMyWindow()},
               label: {Image(systemName: "paperplane")})
            .padding()
    }

    func openMyWindow()
    {
        // handle previously opened window here somehow if needed
        guard windowRef == nil else { return }

        windowRef = NSWindow(
            contentRect: NSRect(x: 100, y: 100, width: 100, height: 600),
            styleMask: [.titled, .closable, .miniaturizable, .resizable, .fullSizeContentView],
            backing: .buffered, defer: false)
        windowRef?.contentView = NSHostingView(rootView: WindowView())
        windowRef?.makeKeyAndOrderFront(nil)
    }

}
  1. 声明 windowRef 在 openMyWindow()

    的范围之外
  2. 如果 window 已经存在,请放在前面,不要创建另一个。

  3. 防止 window 在关闭时被释放,

    • windowRef.isReleasedWhenClosed = false(如下所示)(documentation),或

    • someGlobalWindowController = NSWindowController(window: w)

    var windowRef: NSWindow? 
    func openMyWindow()
    {
        if let curWindow = windowRef {
            curWindow.makeKeyAndOrderFront(nil)
            return
        }
        let w = NSWindow(
            contentRect: NSRect(x: 100, y: 100, width: 100, height: 600),
            styleMask: [.titled, .closable, .miniaturizable, .resizable, .fullSizeContentView],
            backing: .buffered, defer: false)
        w.contentView = NSHostingView(rootView: WindowView())
        w.makeKeyAndOrderFront(nil)
        w.isReleasedWhenClosed = false // <--- important
        windowRef = w
    }