Settings

repository·main·Indexed 23 days ago

https://github.com/sindresorhus/settings

A Swift package for macOS developers to implement human-interface-guideline-compliant settings windows. It supports both AppKit via the SettingsPane protocol and SwiftUI using Settings.Pane, Settings.Container, and Settings.Section. The library provides a SettingsWindowController to manage window lifecycle and tab styles, including .toolbarItems and .segmentedControl.

Tokens
1.5K
Snippets
5
Records
7
Agent score
32%

What's inside Settings

  1. Create SwiftUI settings panes

    main

    For macOS 10.15 or later, you can create panes using SwiftUI. Use Settings.Pane to define the pane's identity and content. To achieve standard macOS alignment, use the bundled Settings.Container and Settings.Section components, or the .settingDescription() view modifier.

    To use SwiftUI panes alongside AppKit NSViewController panes, wrap the SwiftUI Settings.Pane in a Settings.PaneHostingController and pass that to the SettingsWindowController.

    struct CustomPane: View {
    	var body: some View {
    		Settings.Container(contentWidth: 450.0) {
    			Settings.Section(title: "Section Title") {
    				// Some view.
    			}
    			Settings.Section(label: {
    				// Custom label aligned on the right side.
    			}) {
    				// Some view.
    			}
    		}
    	}
    }
    
    // Wrapping for AppKit compatibility:
    let CustomViewSettingsPaneViewController: () -> SettingsPane = {
    	let paneView = Settings.Pane(
    		 identifier: …,
    		 title: …,
    		 toolbarIcon: NSImage(…)
    	) {
    		CustomPane()
    	}
    
    	return Settings.PaneHostingController(paneView: paneView)
    }
  2. Initialize and show the Settings window

    main

    In your AppDelegate, initialize a SettingsWindowController by passing an array of SettingsPane objects. To display the window (for example, in response to a menu item action), call .show() on the controller instance.

    import Cocoa
    import Settings
    
    @main
    final class AppDelegate: NSObject, NSApplicationDelegate {
    	@IBOutlet private var window: NSWindow!
    
    	private lazy var settingsWindowController = SettingsWindowController(
    		panes: [
    			GeneralSettingsViewController(),
    			AdvancedSettingsViewController()
    		]
    	)
    
    	func applicationDidFinishLaunching(_ notification: Notification) {}
    
    	@IBAction
    	func settingsMenuItemActionHandler(_ sender: NSMenuItem) {
    		settingsWindowController.show()
    	}
    }
  3. Configure Settings tab styles

    main

    You can choose between two visual styles for the settings tabs when initializing SettingsWindowController via the style parameter:

    • .toolbarItems: The default style using NSToolbarItems.
    • .segmentedControl: A style using an NSSegmentedControl for tab switching.
    private lazy var settingsWindowController = SettingsWindowController(
    	panes: [
    		GeneralSettingsViewController(),
    		AdvancedSettingsViewController()
    	],
    	style: .segmentedControl
    )
  4. Troubleshoot Settings window visibility

    main

    If the settings window does not appear when calling .show(), it is likely because the view controller does not have a defined size or is not using auto-layout.

    Fix: Ensure you are using auto-layout or set an explicit size using preferredContentSize within the view controller's viewDidLoad() method.

  5. Reference: SettingsWindowController API

    main

    The SettingsWindowController manages the settings window lifecycle and tab switching.

    Initializers:

    • init(panes: [SettingsPane], style: Settings.Style = .toolbarItems, animated: Bool = true, hidesToolbarForSingleItem: Bool = true)
    • init(panes: [SettingsPaneConvertible], style: Settings.Style = .toolbarItems, animated: Bool = true, hidesToolbarForSingleItem: Bool = true)

    Methods:

    • show(pane: Settings.PaneIdentifier? = nil): Displays the window, optionally focusing on a specific pane.
    • close(): Closes the window (inherited from NSWindowController).
  6. Implement AppKit settings panes using SettingsPane

    main

    To create settings panes using AppKit, implement the SettingsPane protocol on your NSViewController. You must provide a paneIdentifier, a paneTitle, and a toolbarItemIcon.

    Note: If you are using the .segmentedControl style, toolbarItemIcon is not required. For macOS versions older than 11, you should provide a fallback for the icon as SF Symbols are not available.

    import Cocoa
    import Settings
    
    final class GeneralSettingsViewController: NSViewController, SettingsPane {
    	let paneIdentifier = Settings.PaneIdentifier.general
    	let paneTitle = "General"
    	let toolbarItemIcon = NSImage(systemSymbolName: "gearshape", accessibilityDescription: "General settings")!
    
    	override var nibName: NSNib.Name? { "GeneralSettingsViewController" }
    
    	override func viewDidLoad() {
    		super.viewDidLoad()
    		// Setup stuff here
    	}
    }