1

I am building a MacOS application which shows a menubar icon with a popover. I am using SwiftUI and building for Monterey only. I would like to change some app settings and I enabled a button inside the popover. Now, then the user presses the button, this should open a standard window where the user can add/change settings. The window is designed using SwiftUI.

enter image description here

So in my code, I tried to do something similar to this

struct ContentView: View {
    var body: some View {
        Text("Hello, World!")
            .frame(maxWidth: .infinity, maxHeight: .infinity)
        Button(action: {openWindow()}) { Text("SETTINGS")}
        Spacer()
    }
}


func openWindow() {
    let window = NSWindow()
    let contentView = ContentView()
    window.aspectRatio = NSSize(width: 400, height: 400)
    window.contentViewController = NSHostingController(rootView: contentView)
    window.makeKey()
}

but nothing happen. So I am wondering few things:

  1. what did I miss with Cocoa here?
  2. shall I use Cocoa for this? Isn't anything more native ?
Ste
  • 283
  • 1
  • 15

1 Answers1

2

Like in a normal SwiftUI app add this in the body of the @main struct:

Settings {
    SettingsView()
}

In the view representing the popover create a button or some other UI element to open the settings window. In the action call this

NSApp.sendAction(Selector(("showPreferencesWindow:")), to: nil, from: nil)
NSApp.activate(ignoringOtherApps: true)

The framework will provide a new window to display the SettingsView

vadian
  • 274,689
  • 30
  • 353
  • 361
  • I think I got closed to it, but the @main is actually old AppDelegate, so this solution proved to work better https://stackoverflow.com/a/62780829/12299030. I had to create another objc function to make it happen – Ste May 15 '22 at 14:17
  • As you wrote *I am using SwiftUI* I highly recommend to use AppDelegate only for creating the Popover and design everything else directly in SwiftUI. Especially the Preferences window is so easy to implement. – vadian May 15 '22 at 14:25