Requirements
macOS 10.13 and later.
Install
Add https://github.com/sindresorhus/Settings
in the “Swift Package Manager” tab in Xcode.
Settings Tab Styles
When you create the SettingsWindowController
, you can choose between the NSToolbarItem
-based style (default) and the NSSegmentedControl
:
// …
private lazy var settingsWindowController = SettingsWindowController(
panes: [
GeneralSettingsViewController(),
AdvancedSettingsViewController()
],
style: .segmentedControl
)
// …
.toolbarItem
style:
.segmentedControl
style:
API
public enum Settings {}
extension Settings {
public enum Style {
case toolbarItems
case segmentedControl
}
}
public protocol SettingsPane: NSViewController {
var paneIdentifier: Settings.PaneIdentifier { get }
var paneTitle: String { get }
var toolbarItemIcon: NSImage { get } // Not required when using the .`segmentedControl` style
}
public final class SettingsWindowController: NSWindowController {
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
)
func show(pane: Settings.PaneIdentifier? = nil)
}
As with any NSWindowController
, call NSWindowController#close()
to close the settings window.
Recommendation
The easiest way to create the user interface within each pane is to use a NSGridView
in Interface Builder. See the example project in this repo for a demo.
Known issues
The settings window doesn’t show
This can happen when you are not using auto-layout or have not set a size for the view controller. You can fix this by either using auto-layout or setting an explicit size, for example, preferredContentSize
in viewDidLoad()
. We intend to fix this.
FAQ
How can I localize the window title?
The SettingsWindowController
adheres to the macOS Human Interface Guidelines and uses this set of rules to determine the window title:
- Multiple settings panes: Uses the currently selected
paneTitle
as the window title. Localize yourpaneTitle
s to get localized window titles. - Single settings pane: Sets the window title to
APPNAME Settings
. The app name is obtained from your app’s bundle. You can localize itsInfo.plist
to customize the title. TheSettings
part is taken from the “Settings…” menu item, see #12. The order of lookup for the app name from your bundle:CFBundleDisplayName
CFBundleName
CFBundleExecutable
- Fall back to
"<Unknown App Name>"
to show you’re missing some settings.
Why should I use this instead of just manually implementing it myself?
It can’t be that hard right? Well, turns out it is:
- The recommended way is to implement it using storyboards. But storyboards… And if you want the segmented control style, you have to implement it programmatically, which is quite complex.
- Even Apple gets it wrong, a lot.
- You have to correctly handle window and tab restoration.
- The window title format depends on whether you have a single or multiple panes.
- It’s difficult to get the transition animation right. A lot of apps have flaky animation between panes.
- You end up having to deal with a lot of gnarly auto-layout complexities.
Related
- Defaults - Swifty and modern UserDefaults
- LaunchAtLogin - Add “Launch at Login” functionality to your macOS app
- KeyboardShortcuts - Add user-customizable global keyboard shortcuts to your macOS app
- DockProgress - Show progress in your app’s Dock icon
- More…
You might also like Sindre’s apps.
Used in these apps
- TableFlip - Visual Markdown table editor by Christian Tietze
- The Archive - Note-taking app by Christian Tietze
- Word Counter - Measuring writer’s productivity by Christian Tietze
- Medis - A Redis GUI by Zihua Li
- OK JSON - A scriptable JSON formatter by Francis Feng
- Menu Helper - A Finder Extension App by Kyle-Ye
Want to tell the world about your app that is using this package? Open a PR!