当前位置: 首页 > 知识库问答 >
问题:

swiftui - macOS 14 SwiftUI App启动时打开设置窗口的替代方法?

傅恺
2024-04-17

swiftUI macos App, 目前只有 设置和 menubar 两个视图,没有主窗体,怎么实现在App启动的时候,打开设置窗口,

在macos 13 的时候可以使用

NSApp.sendAction (Selector(("showSettingsWindow:")),to:nil, from:nil)

但是macos 14 的时候,showSettingsWindow 会提示使用,SettingsLink,SettingsLink是视图,又不能在生命周期中使用。

共有1个答案

华章横
2024-04-17

stackoverflow 上找到了答案
扩展 NSApplication 一个 openSettings 方法 ,然后在 appDelegate 的applicationDidFinishLaunching 中调用

代码调用

func applicationDidFinishLaunching(_ aNotification: Notification) {        NSApplication.shared.openSettings()           }

拓展 NSApplication

// https://stackoverflow.com/a/76714125/19625526private let kAppMenuInternalIdentifier = "app"private let kSettingsLocalizedStringKey = "Settings\\U2026"extension NSApplication {    /// Open the application settings/preferences window.    func openSettings() {        // macOS 14 Sonoma        if let internalItemAction = NSApp.mainMenu?.item(            withInternalIdentifier: kAppMenuInternalIdentifier        )?.submenu?.item(            withLocalizedTitle: kSettingsLocalizedStringKey        )?.internalItemAction {            internalItemAction()            return        }        guard let delegate = NSApp.delegate else { return }        // macOS 13 Ventura        var selector = Selector(("showSettingsWindow:"))        if delegate.responds(to: selector) {            delegate.perform(selector, with: nil, with: nil)            return        }        // macOS 12 Monterrey        selector = Selector(("showPreferencesWindow:"))        if delegate.responds(to: selector) {            delegate.perform(selector, with: nil, with: nil)            return        }    }}// MARK: - NSMenuItem (Private)extension NSMenuItem {        /// An internal SwiftUI menu item identifier that should be a public property on `NSMenuItem`.    var internalIdentifier: String? {        guard let id = Mirror.firstChild(            withLabel: "id", in: self        )?.value else {            return nil;        }                return "\(id)";    }        /// A callback which is associated directly with this `NSMenuItem`.    var internalItemAction: (() -> Void)? {        guard            let platformItemAction = Mirror.firstChild(                withLabel: "platformItemAction", in: self)?.value,            let typeErasedCallback = Mirror.firstChild(                in: platformItemAction)?.value        else {            return nil;        }                    return Mirror.firstChild(            in: typeErasedCallback        )?.value as? () -> Void;    }    }// MARK: - NSMenu (Private)extension NSMenu {    /// Get the first `NSMenuItem` whose internal identifier string matches the given value.    func item(withInternalIdentifier identifier: String) -> NSMenuItem? {        self.items.first(where: {            $0.internalIdentifier?.elementsEqual(identifier) ?? false        })    }        /// Get the first `NSMenuItem` whose title is equivalent to the localized string referenced    /// by the given localized string key in the localization table identified by the given table name    /// from the bundle located at the given bundle path.    func item(        withLocalizedTitle localizedTitleKey: String,        inTable tableName: String = "MenuCommands",        fromBundle bundlePath: String = "/System/Library/Frameworks/AppKit.framework"    ) -> NSMenuItem? {        guard let localizationResource = Bundle(path: bundlePath) else {            return nil;        }                return self.item(withTitle: NSLocalizedString(            localizedTitleKey,            tableName: tableName,            bundle: localizationResource,            comment: ""));    }    }// MARK: - Mirror (Helper)fileprivate extension Mirror {        /// The unconditional first child of the reflection subject.    var firstChild: Child? { self.children.first }        /// The first child of the reflection subject whose label matches the given string.    func firstChild(withLabel label: String) -> Child? {        self.children.first(where: {            $0.label?.elementsEqual(label) ?? false        })    }        /// The unconditional first child of the given subject.    static func firstChild(in subject: Any) -> Child? {        Mirror(reflecting: subject).firstChild    }        /// The first child of the given subject whose label matches the given string.    static func firstChild(        withLabel label: String, in subject: Any    ) -> Child? {        Mirror(reflecting: subject).firstChild(withLabel: label)    }    }

参考链接

 类似资料:
  • 我试图创建一个程序,它有一个tkinter窗口打开,然后当你按下一个按钮,它关闭tkinter窗口,打开一个pyplay窗口。然而,当我点击按钮打开pyplay窗口时,它会打开pyplay窗口,而tkinter窗口保持打开状态。 代码: 我还尝试使用: 我怎样才能解决这个问题?(我正在MacOS 11.1上运行Python 3.7.7)

  • 本文向大家介绍在新窗口打开链接的方法是什么?那怎么设置全站链接都在新窗口打开?相关面试题,主要包含被问及在新窗口打开链接的方法是什么?那怎么设置全站链接都在新窗口打开?时的应答技巧和注意事项,需要的朋友参考一下 希望通过合理的书写,来降低阅读的门槛。(把以上答案合并优化了一下,取百家之长) 通过给 标签设置 属性,即可实现链接在新窗口打开; 在 中为 元素设置 即可为所有的链接设置默认的打开方式为

  • 我有A. fxml和B. fxml。运行Java应用程序覆盖启动方法。我想每40分钟循环(5次){打开新阶段B. fxml并等待stage.close,如果阶段关闭继续循环打开新阶段B fxml。循环五次。我尝试定时器timerment我不能。我尝试JavaFX服务我不能。我创建My线程扩展线程对象。这一次,我无法控制下一阶段的循环。当用于声明开始打开5阶段。但是我想循环等待当前阶段关闭,然后进入

  • 我正在使用Pygame模块制作一个简单的游戏。我需要Tkinter窗口与Pygame窗口一起打开。 每当我试图打开两个窗口时,第二个窗口只有在我杀死第一个窗口后才会打开。 现在,我能想到的唯一解决方案是使用多线程。但是,我无法实现它。 我该怎么做呢?我真的很感激这里的帮助。谢谢你!

  • 在Chrome中打开新窗口时,有没有办法自动打开开发者工具?

  • 查看这段代码,它们展示了一种在登录后显示新窗口的方法。当用户名和密码是正确的,它打开新的对话框。我想要一个按钮点击打开新的对话框,而不检查用户名和密码。