SSkilltecabyclaudinhocode
Enviar skill
← Voltar para o catálogo

swiftui-mac-pro-skill

Desenvolvimento

Use for ALL macOS SwiftUI app dev — building, editing, debugging `.swift` files on macOS targets. Current focus: macOS 15 Sequoia + macOS 26 Tahoe; future macOS added as Apple ships. Covers window scenes (WindowGroup, Window, MenuBarExtra, Settings, DocumentGroup), navigation (NavigationSplitView, NavigationStack), toolbars (.toolbar/NSToolbar), main menu (CommandGroup, .commands), AppKit interop

1estrelas
Ver no GitHub ↗Autor: toankhontechLicença: MIT

swiftui-mac-pro-skill — Production Mac SwiftUI for Claude Code

Currently focused on macOS 15 Sequoia (baseline) + macOS 26 Tahoe (Liquid Glass opt-in). These are the most-deployed macOS versions in 2026. Future macOS releases will be added as Apple ships them. The skill is version-flexible: APIs gated by if #available(...) keep older targets working.

When this skill applies

Use these instructions for SwiftUI work whose deployment target is macOS 15 Sequoia. The skill is macOS 15-first: every code path must run on macOS 15. macOS 26 (Tahoe) Liquid Glass features are allowed only as opt-in enhancements gated with if #available(macOS 26.0, *) — see references/macos26-optin.md.

Code must compile cleanly under Swift 5 and Swift 6 language modes (including the Swift 6.2 default-isolation defaults if the project enables them). New code should not rely on patterns that become errors when strict concurrency is on. See references/swift6-concurrency.md.

Distribution-aware: Every Mac project ships to one of: Mac App Store (App Sandbox required), Direct distribution via Developer ID (Hardened Runtime required, Sandbox optional), or both. Before introducing any API that touches the file system, network, devices, or other apps, check the project's .entitlements file. If unstated, assume both modes must work — that's the most restrictive path.

Respect the existing project. Before changing code, check the deployment target, Swift language mode, persistence stack, sandbox status, and naming conventions. Existing settings win unless the user explicitly asks to migrate. Never introduce macOS 16+ / macOS 26 APIs without an availability gate.

Working rules

  1. Match the app's existing architecture, deployment target, and naming before introducing a new pattern.
  2. Distribution-aware: never assume sandbox on/off — check .entitlements first. If not stated, assume both Mac App Store + Direct must work.
  3. Prefer Apple-built frameworks. Fall to AppKit when SwiftUI cannot deliver pro-grade UX (NSToolbar customization, NSWindowController state, custom titlebar, NSStatusItem behavior).
  4. Write complete, compilable snippets — include imports, no undefined placeholders inside "complete" examples.
  5. Build or typecheck when a local project is available before declaring code done.
  6. Never introduce macOS 16+ / macOS 26 APIs without if #available(macOS 26.0, *) gate.
  7. Swift 6.2 default-isolation aware: explicit @MainActor on view models even when project sets defaultActorIsolation = MainActor (consistency + readability).

Deprecated patterns to avoid

These are deprecated as of macOS 15 SwiftUI. Each has a recommended replacement and a brief reason — knowing why helps when you encounter edge cases.

Navigation

  • NavigationViewNavigationSplitView (sidebar/detail) or NavigationStack (push). NavigationView produces unpredictable layout on macOS and is being removed.
  • NavigationLink(isActive:), tag:, selection:List(selection:) + .navigationDestination(for:) with typed values. Old initializers don't compose with typed paths and break programmatic back-navigation.

State / Observation

  • ObservableObject/@Published/@ObservedObject/@StateObject@Observable + @State/@Bindable. Observation tracks reads at the property level; @Published invalidates on any change.
  • @StateObject for an @Observable class → @State. CRITICAL: the migration is NOT 1:1 — @StateObject was lazy/once-per-lifetime; @State initializes eagerly. If your view model has a heavy initializer (network call, file I/O, model load), the regression can cause double-fetches or re-init storms. Refactor the heavy work into a .task body or move it behind a lazy property.
  • ReferenceFileDocument still requires ObservableObject conformance (not yet @Observable-native, verified 2026-05-06). Keep @Published properties for that protocol only.

Previews

  • PreviewProvider#Preview.

Alerts and dialogs

  • Alert / ActionSheet structs → .alert(...) / .confirmationDialog(...) modifiers.

Lifecycle

  • .onChange(of:perform:) (single-parameter closure) → zero- or two-parameter overload ({ } or { old, new in }).
  • Task { … } inside .onAppear for initial async load → .task (or .task(id:)). .task cancels automatically on disappear.

Styling and gestures

  • .animation(_:) (broad view-level) → .animation(_:value:) or withAnimation { … }.
  • .accentColor(_:) → asset catalog accent or .tint(_:).
  • Text(...).onTapGesture for tappable controls → Button.

Tabs

  • .tabItemTab (macOS 15+) for new code. .tabItem is soft-deprecated in macOS 15 but not yet hard-removed.
  • Nuance for Settings scene specifically: both .tabItem and Tab render the same underlying NSTabView; Apple's own samples (e.g., Backyard Birds, WWDC24) still use .tabItem for Settings. Migration is code cleanliness, not API removal urgency for that case.

AppKit lifecycle

  • NSApp.activate(ignoringOtherApps: true)NSApp.activate() (macOS 14+). Old form deprecated; emits runtime warning on macOS 15 because it ignores activation policy. New form respects the policy and is the only correct call going forward.
  • UserDefaults.standard.synchronize() → remove the call entirely. No-op since macOS 10.12 (2016). Apple docs: "This method is unnecessary and shouldn't be used."
  • NSApp.sendAction(Selector(("showSettingsWindow:")), to: nil, from: nil)@Environment(\.openSettings) + openSettings() (macOS 14+). The selector form is private API and brittle; the environment value is the official, type-safe replacement.

Window

  • .background(Color) for window background → .containerBackground(_:for: .window) (macOS 14+).
  • NSSavePanel/NSOpenPanel direct presentation → .fileImporter(_:) / .fileExporter(_:) SwiftUI modifiers (macOS 11+) where possible.

macOS 26 features — opt-in via availability gates

Liquid Glass APIs (glassEffect, Glass, GlassEffectContainer, .buttonStyle(.glass), Observations, tabBarMinimizeBehavior) crash on macOS 15. Always gate:

if #available(macOS 26.0, *) {
    SomeView().glassEffect(.regular)
} else {
    SomeView()
}

Liquid Glass auto-adopts on toolbars/sidebars/sheets when the app is recompiled with Xcode 26 — no code change needed for system chrome. See references/macos26-optin.md.

Window scenes

The biggest cognitive shift from iOS to Mac SwiftUI is the Scene system. Every Mac app has one or more Scenes that define windows. Pick the right one:

SceneUse whenmacOS available
WindowGroupMulti-instance content; user expects File > New Window11+
WindowGroup(for: T.self)One window per data value (open Document X brings existing to front if open)13+
WindowSingle uniquely-identified window (Inspector, Welcome, About)13+
SettingsApp preferences — auto-wires Settings… menu and Cmd+,11+
MenuBarExtraStatus-bar utility13+
DocumentGroupFile-backed documents with Open/Save/Recent11+

Minimal example combining the most common scenes:

import SwiftUI

@main
struct MyApp: App {
    var body: some Scene {
        WindowGroup {
            ContentView()
        }
        .windowToolbarStyle(.unified)

        Window("Inspector", id: "inspector") {
            InspectorView()
        }
        .windowLevel(.floating)

        Settings {
            SettingsView()
        }

        MenuBarExtra("Status", systemImage: "star") {
            StatusMenu()
        }
        .menuBarExtraStyle(.menu)
    }
}

For multi-window patterns (@FocusedValue, \.openWindow, .handlesExternalEvents, state restoration), see [references/windows-and-sce

Como adicionar

/plugin marketplace add toankhontech/swiftui-mac-pro-skill

O comando exato pode variar conforme o repositório. Confira o README no GitHub.

Comentários · Nenhum comentário

Entre para comentar. Entrar

  • Ainda não há comentários. Seja o primeiro.