Forked from stephancasas/NSApplication+openSettings.swift
Created
December 4, 2023 08:44
-
-
Save gopalkrishnareddy/2b8d9bdd73ae78350258fd0241aa32cd to your computer and use it in GitHub Desktop.
An extension enabling global access to settings scene of a macOS SwiftUI application.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// | |
// NSApplication+openSettings.swift | |
// | |
// Created by Stephan Casas on 12/3/23. | |
// | |
import SwiftUI; | |
extension NSApplication { | |
/// Open the application settings/preferences window. | |
func openSettings() { | |
// macOS 14 Sonoma | |
if let internalItemAction = NSApp.mainMenu?.item( | |
withInternalIdentifier: "app" | |
)?.submenu?.item( | |
withAction: Selector(("menuAction:")) | |
)?.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 action matches the given selector. | |
func item(withAction action: Selector) -> NSMenuItem? { | |
self.items.first(where: { | |
$0.action == action | |
}) | |
} | |
} | |
// 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) | |
} | |
} | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment