| FazBrowse GitHub Viewer | Trending | | Home |
| Tools: [Download Repo ZIP] [Original HTTPS Page] |
| Name | Name | Last commit date | ||
|---|---|---|---|---|
Note
Xcode 16 now makes Apple's previously-private openSettings environment method public, and back-ports it to macOS 14.
While this is welcome progress, it still is only incremental and the vast majority of SettingsAccess' functionality is still needed in many scenarios.
SettingsAccess 2.0.0 adds support for compiling with Xcode 16 by renaming its openSettings method to openSettingsLegacy. For projects targeting macOS 14+ you may opt to use the new native openSettings method. For projects targeting older versions of macOS, use openSettingsLegacy.
As of macOS 14 Sonoma:
Apple completely removed the ability to open the SwiftUI Settings scene using legacy NSApp.sendAction() method using the showSettingsWindow: (macOS 13) or showPreferencesWindow: (macOS 12 and earlier) selectors. The only available method of opening the Settings scene (apart from the App menu → Settings menu item) is to use the new SettingsLink view.
This presents two major restrictions:
These restrictions become problematic in many scenarios. Some examples that are currently impossible without SettingsAccess:
See Getting Started below for example usage.
Add SettingsAccess as a dependency using Swift Package Manager.
In an app project or framework, in Xcode:
Select the menu: File → Swift Packages → Add Package Dependency...
Enter this URL: https://github.com/orchetect/SettingsAccess
In a Swift Package, add it to the Package.swift dependencies:
.package(url: "https://github.com/orchetect/SettingsAccess", from: "2.1.0")Import the library.
import SettingsAccessAttach the openSettingsAccess view modifier to the base view whose subviews needs access to the openSettingsLegacy method.
@main
struct MyApp: App {
var body: some Scene {
WindowGroup {
ContentView()
.openSettingsAccess()
}
Settings { SettingsView() }
}
}In any subview where needed, add the environment method declaration. Then the Settings scene may be opened programmatically by calling this method.
struct ContentView: View {
@Environment(\.openSettingsLegacy) private var openSettingsLegacy
var body: some View {
Button("Open Settings") { try? openSettingsLegacy() }
}
}If using a menu-based MenuBarExtra, do not apply openSettingsAccess() to the menu content. openSettingsLegacy() cannot be used there due to limitations of SwiftUI.
Instead, use the custom SettingsLink initializer to add a Settings menu item capable of running code before and/or after opening the Settings scene.
@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) }
}
}It is possible to replace your app's standard "About" menu item and have it open the Settings window to a specific tab instead. SettingsAccess makes this possible on older versions of macOS prior to the openSettings() environment command being available.
Using the custom SettingsLink with pre- and post- actions, you are able to set a UserDefaults-stored variable to the about page prior to the Settings window opening.
@main
struct MyApp: App {
@AppStorage("selectedSettingsPage") private var selectedSettingsPage: SettingsPage = .general
var body: some Scene {
WindowGroup {
ContentView()
}
.commands {
CommandGroup(replacing: .appInfo) {
SettingsLink {
Text("About...")
} preAction: {
selectedSettingsPage = .about
} postAction: {
// none
}
}
}
Settings { SettingsView() }
}
}
enum SettingsPage: String {
case general
case about
}
struct SettingsView: View {
@AppStorage("selectedSettingsPage") private var selectedSettingsPage: SettingsPage = .general
var body: some View {
TabView(selection: $selectedSettingsPage) {
GeneralView()
.tabItem {
Label("General", systemImage: "gear")
}
.tag(SettingsPage.general)
AboutView()
.tabItem {
Label("About", systemImage: "info.bubble.fill")
}
.tag(SettingsPage.about)
}
}
}Try the Demo example project to see the library in action.
Requires Xcode 15.0 or higher to build.
Once compiled, supports macOS 11.0 or higher.
SettingsLink is a view that wraps a standard SwiftUI Button and prior to Xcode 16, its action calls a private environment method called _openSettings. (As of Xcode 16 this method is now available publicly. See the Xcode 16 Update section for more information.)
It is worth noting that due to how SwiftUI Button works, it is impossible to attach a simultaneous gesture to attempt to detect a button press.
The solution is the use of a custom Button style which, when applied directly to SettingsLink, allows us to capture the Button press action and execute arbitrary code closures before and after the user presses the button. We can also export this method as an environment method called openSettingsLegacy that can be used in a backwards-compatible fashion prior to openSettings being made public by Apple.
More info and a deep-dive can be found in this reddit post.
Coded by a bunch of 🐹 hamsters in a trenchcoat that calls itself @orchetect.
Licensed under the MIT license. See LICENSE for details.
If you enjoy using SettingsAccess and want to contribute to open-source financially, GitHub sponsorship is much appreciated. Feedback and code contributions are also welcome.
Please do not email maintainers for technical support. Several options are available for issues and questions:
Contributions are welcome. Posting in Discussions first prior to new submitting PRs for features or modifications is encouraged.
In an effort to maintain a consistent level of code quality and safety, this repository was built by hand and is maintained without the use of AI code generation.
AI-assisted contributions are welcome, but must remain modest in scope, maintain the same degree of quality and care, and be thoroughly vetted before acceptance.
| Back | FazBrowse Home | New Git URL |