【问题标题】:Button to open view in new window SwiftUI 5.3 for Mac OS X用于在新窗口中打开视图的按钮 SwiftUI 5.3 for Mac OS X
【发布时间】:2023-03-21 09:08:01
【问题描述】:

我想要一个按钮来打开一个新窗口并在 SwiftUI for MacOS 中加载一个视图(用于应用程序的首选项),但我不确定正确的方法。

我尝试创建一个函数并从有效的按钮操作中调用它,但在关闭新窗口时应用程序崩溃:

线程 1:EXC_BAD_ACCESS(代码=1,地址=0x20)

这是我的功能:

func openPreferencesWindow() {
    var preferencesWindow: NSWindow!
    let preferencesView = PreferencesView()
    // Create the preferences window and set content
    preferencesWindow = NSWindow(
        contentRect: NSRect(x: 20, y: 20, width: 480, height: 300),
        styleMask: [.titled, .closable, .miniaturizable, .resizable, .fullSizeContentView],
        backing: .buffered,
        defer: false)
    preferencesWindow.center()
    preferencesWindow.setFrameAutosaveName("Preferences")
    preferencesWindow.contentView = NSHostingView(rootView: preferencesView)
    preferencesWindow.makeKeyAndOrderFront(nil)
}

这是我的按钮调用它:

Button(action: {
    openPreferencesWindow()
}) {
    Text("Preferences").font(.largeTitle).foregroundColor(.primary)
}

我觉得应该在 AppDelegate 中构建窗口,但我不确定如何调用它。

【问题讨论】:

    标签: macos button swiftui window nswindow


    【解决方案1】:

    您需要保留对创建的首选项窗口的引用(如主窗口)。

    这是可能的解决方案(使用 Xcode 11.4 / macOS 10.15.5 测试)

    @NSApplicationMain
    class AppDelegate: NSObject, NSApplicationDelegate, NSWindowDelegate {
    
        var window: NSWindow!
        var preferencesWindow: NSWindow!    // << here
    
        @objc func openPreferencesWindow() {
            if nil == preferencesWindow {      // create once !!
                let preferencesView = PreferencesView()
                // Create the preferences window and set content
                preferencesWindow = NSWindow(
                    contentRect: NSRect(x: 20, y: 20, width: 480, height: 300),
                    styleMask: [.titled, .closable, .miniaturizable, .resizable, .fullSizeContentView],
                    backing: .buffered,
                    defer: false)
                preferencesWindow.center()
                preferencesWindow.setFrameAutosaveName("Preferences")
                preferencesWindow.isReleasedWhenClosed = false
                preferencesWindow.contentView = NSHostingView(rootView: preferencesView)
            }
            preferencesWindow.makeKeyAndOrderFront(nil)
        }
    
        // ... other code
    

    现在按钮看起来像

    Button(action: {
        NSApp.sendAction(#selector(AppDelegate.openPreferencesWindow), to: nil, from:nil)
    }) {
        Text("Preferences").font(.largeTitle).foregroundColor(.primary)
    }
    

    【讨论】:

    • 效果很好,谢谢!你能向我解释一下(我对目标c不是很有经验)这个机制让我明白吗? 1. 为什么必须将@objc 属性应用于函数? 2、为什么我们必须用NSApp调用函数而不是直接调用。 3、为什么NSWindow实例在AppDelegate中总是要有引用?
    • 是的,我也想知道。没有所有 3 点,它对我有用。
    • 优秀的解决方案@Asperi,像往常一样!非常感谢。
    • 如何将工具栏项或导航标题添加到该视图? .toolbar / .navigationTitle 的默认方式无法正常工作。
    • @HackMac window.title = "Window title"。使用NSHostingView时,navigationTitle不起作用,需要在窗口上设置标题。
    猜你喜欢
    • 2011-12-31
    • 2020-11-04
    • 2010-11-12
    • 1970-01-01
    • 1970-01-01
    • 2011-06-06
    • 2020-12-13
    • 2013-07-20
    • 1970-01-01
    相关资源
    最近更新 更多