On macOS 14, the way to open the settings has changed. The code I have been using so far is:
if #available(macOS 13, *) {
NSApp.sendAction(Selector(("showSettingsWindow:")), to: nil, from: nil)
} else {
NSApp.sendAction(Selector(("showPreferencesWindow:")), to: nil, from: nil)
}
On macOS 14, this code throws the error message Please use SettingsLink for opening the Settings scene.
Actual Question: How can I open the app settings programmatically from AppKit in macOS 14 (Sonoma)
This is the new method:
@main
struct MyApp: App {
var body: some Scene {
WindowGroup {
RootScreen()
}
Settings {
SettingsScreen()
}
MenuBarExtra("My App", systemImage: "mic.fill") {
SettingsLink {
Text("Settings")
}
}
.keyboardShortcut(".", modifiers: .command)
}
NSMenu
https://github.com/orchetect/SettingsAccess
import SettingsAccess
final class AppDelegateMac: NSObject, NSApplicationDelegate {
private func setupStatusBar() {
let menu = NSMenu()
menu.addItem(NSMenuItem(title: "Settings", action: #selector(openSettings), keyEquivalent: ""))
statusBarItem = NSStatusBar.system.statusItem(withLength: CGFloat(NSStatusItem.variableLength))
statusBarItem!.menu = menu
statusBarItem!.button?.image = NSImage(systemSymbolName: "mic.fill", accessibilityDescription: nil)
}
@objc private func openSettings() {
if #available(macOS 14, *) {
appState?.openSettingsSignal.send()
}
}
}
---
import SettingsAccess
@main
struct MyApp: App {
var body: some Scene {
WindowGroup {
RootScreen()
.openSettingsAccess()
}
}
}
---
struct RootScreen: View {
private let appState: AppState
@Environment(\.openSettings) var openSettings
var body: some View {
}
.onReceive(appState.openSettingsSignal) {
try? openSettings()
}
}
---
struct AppState {
let openSettingsSignal = PassthroughSubject<Void, Never>()
}