I would like to have a button to open a new window and load a view (for the app's Preferences) in SwiftUI for MacOS but am unsure of the correct way to do it.
I tried creating a function and calling it from the button action which works but on closing the new window the app crashes with:
Thread 1: EXC_BAD_ACCESS (code=1, address=0x20)
This is my function:
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)
}
And this is my button calling it:
Button(action: {
openPreferencesWindow()
}) {
Text("Preferences").font(.largeTitle).foregroundColor(.primary)
}
I feel like the window should be constructed in AppDelegate but I'm not sure how I would then call it.
You need to keep reference to created preferences window (like to the main window).
Here is possible solution (tested with 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
and now button would look like
Button(action: {
NSApp.sendAction(#selector(AppDelegate.openPreferencesWindow), to: nil, from:nil)
}) {
Text("Preferences").font(.largeTitle).foregroundColor(.primary)
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With