Windows and commands
Add a Settings scene
Store small preferences with AppStorage and let SwiftUI connect a normal settings window to the application menu.
12 minute lesson
Every Mac app has a Settings item in its application menu, with ⌘, as the shortcut. Users do not think about this — they expect it, the way they expect Quit at the bottom of the same menu.
SwiftUI wires all of it from one scene declaration. Add it beside your other scenes:
Settings {
SettingsView()
}
That is the whole integration. The menu item appears, ⌘, works, and macOS presents a standard settings window. You never write “open the settings window” code.
Inside, build a form. For small preferences, @AppStorage connects a property straight to UserDefaults:
struct SettingsView: View {
@AppStorage("showLineNumbers") private var showLineNumbers = true
@AppStorage("fontSize") private var fontSize = 14.0
var body: some View {
Form {
Toggle("Show line numbers", isOn: $showLineNumbers)
Slider(value: $fontSize, in: 10...24) {
Text("Font size")
}
}
.padding()
.frame(width: 350)
}
}
Reading the same key elsewhere gives you a live value. Declare @AppStorage("showLineNumbers") in the note detail view and the UI updates the moment the toggle changes — no notification code, no manual refresh.
Two rules keep this clean. First, key names are permanent: rename "showLineNumbers" in a later version and every user silently loses their preference. Define keys once and never touch them again. Second, every key needs a sensible default, because the first launch has no stored value.
If settings grow, split them into tabs the way system apps do:
TabView {
GeneralSettings()
.tabItem { Label("General", systemImage: "gearshape") }
EditorSettings()
.tabItem { Label("Editor", systemImage: "textformat") }
}
Know what does not belong here. UserDefaults stores plain text in a plist anyone can read with one Terminal command, so API tokens and passwords go in the Keychain — we will do exactly that in a later lesson. Primary documents, like the notes themselves, need real files with atomic saves, not preference storage.
Verify by running the app: the application menu shows Settings…, ⌘, opens the window, toggling the switch updates the editor immediately, and the value survives a relaunch. If the menu item is missing, your Settings scene is probably declared inside another scene’s body instead of beside it.
Lesson completed