注意
Xcode 16 现在将 Apple 之前私有的 openSettings
环境方法公开,并将其向后移植到 macOS 14。
虽然这是一个值得欢迎的进步,但这仍然只是渐进式的,在许多情况下仍然需要 SettingsAccess 的绝大部分功能。
SettingsAccess 2.0.0 通过将其 openSettings
方法重命名为 openSettingsLegacy
,增加了对使用 Xcode 16 编译的支持。对于目标 macOS 14+ 的项目,您可以选择使用新的原生 openSettings
方法。对于目标 macOS 较旧版本的项目,请使用 openSettingsLegacy
。
截至 macOS 14 Sonoma
Apple 完全移除了使用旧版 NSApp.sendAction()
方法和 showSettingsWindow:
(macOS 13) 或 showPreferencesWindow:
(macOS 12 及更早版本) 选择器打开 SwiftUI 设置场景的能力。打开“设置”场景的唯一可用方法(除了应用程序菜单 → 设置菜单项之外)是使用新的 SettingsLink
视图。
这带来了两个主要的限制
Settings
场景打开之前或之后运行,则没有简单的方法来检测用户何时单击了此按钮。Settings
场景的方法。(更新:Xcode 16 增加了支持,但仍然有限。)这些限制在许多情况下变得有问题。以下是一些目前在没有 SettingsAccess 的情况下不可能实现的示例
MenuBarExtra
,并且想要有一个按钮来激活应用程序,打开 Settings
,然后还关闭窗口。Settings
场景。openSettingsLegacy()
的 SwiftUI 环境方法,可以在视图层次结构的任何位置调用它,以编程方式打开 Settings
场景。SettingsLink
提供了一个初始化器,它提供了两个闭包,允许在打开 Settings
场景之前和/或之后执行任意代码。请参阅下面的入门指南以获取示例用法。
SettingsLink
的内部限制。openSettingsLegacy()
在基于 menu
的 MenuBarExtra
中不可用。在这种情况下,可以使用自定义的 SettingsLink
初始化器来运行在打开 Settings
场景之前/之后的代码。使用 Swift Package Manager 将 SettingsAccess 添加为依赖项。
在 Xcode 的应用程序项目或框架中
选择菜单:文件 → Swift Packages → Add Package Dependency...
输入此 URL:https://github.com/orchetect/SettingsAccess
在 Swift Package 中,将其添加到 Package.swift 依赖项中
.package(url: "https://github.com/orchetect/SettingsAccess", from: "2.1.0")
导入库。
import SettingsAccess
将 openSettingsAccess
视图修饰符附加到需要访问 openSettingsLegacy
方法的基础视图。
@main
struct MyApp: App {
var body: some Scene {
WindowGroup {
ContentView()
.openSettingsAccess()
}
Settings { SettingsView() }
}
}
在任何需要的子视图中,添加环境方法声明。然后可以通过调用此方法以编程方式打开 Settings
场景。
struct ContentView: View {
@Environment(\.openSettingsLegacy) private var openSettingsLegacy
var body: some View {
Button("Open Settings") { try? openSettingsLegacy() }
}
}
如果使用基于菜单的 MenuBarExtra
,请不要将 openSettingsAccess()
应用于菜单内容。由于 SwiftUI 的限制,openSettingsLegacy()
在那里无法使用。
相反,请使用自定义的 SettingsLink
初始化器来添加一个“设置”菜单项,该菜单项能够在打开 Settings
场景之前和/或之后运行代码。
@main
struct MyApp: App {
var body: some Scene {
MenuBarExtra {
AppMenuView()
// Do not attach .openSettingsAccess()
}
Settings { SettingsView() }
}
}
struct AppMenuView: View {
var body: some View {
SettingsLink {
Text("Settings...")
} preAction: {
// code to run before Settings opens
} postAction: {
// code to run after Settings opens
}
Button("Quit") { NSApp.terminate(nil) }
}
}
尝试 Demo 示例项目,查看库的实际应用。
需要 Xcode 15.0 或更高版本才能构建。
编译后,支持 macOS 11.0 或更高版本。
SettingsLink
是一个包装标准 SwiftUI Button
的视图,在 Xcode 16 之前,其操作调用了一个名为 _openSettings
的私有环境方法。(从 Xcode 16 开始,此方法现在公开可用。有关更多信息,请参阅 Xcode 16 更新 部分。)
值得注意的是,由于 SwiftUI Button
的工作方式,不可能附加同时手势来尝试检测按钮按下。
解决方案是使用自定义的 Button
样式,当直接应用于 SettingsLink
时,允许我们捕获 Button
按下操作,并在用户按下按钮之前和之后执行任意代码闭包。我们还可以将此方法导出为名为 openSettingsLegacy
的环境方法,该方法可以在 Apple 公开 openSettings
之前以向后兼容的方式使用。
更多信息和深入探讨可以在 这篇 reddit 帖子 中找到。
由一群穿着外套的 🐹 仓鼠编码,它们自称为 @orchetect。
根据 MIT 许可证获得许可。有关详细信息,请参阅 LICENSE。
如果您喜欢使用 SettingsAccess 并希望在经济上为开源做出贡献,GitHub 赞助将不胜感激。也欢迎反馈和代码贡献。
欢迎贡献。鼓励在新提交功能或修改的 PR 之前先在 Discussions 中发帖。