mcpField
M
macos-app-structure

macos-app-structure

github.com/makgunay開発144 回インストール38 週間前に更新
リポジトリ

macos-app-structure について

Mac アプリを構築またはレビューする開発者向けの、SwiftUI macOS アプリ構成スキルです。シーン選択、ウィンドウ、ナビゲーション、プロジェクト構成、プラットフォーム固有の注意点を扱います。

主な機能

  1. 01macOS のシーンとウィンドウのパターン
  2. 02メニューバーアプリの構成
  3. 03サイドバーナビゲーションの指針
  4. 04プロジェクト構成の規約
  5. 05Info.plist と権限設定の参照
  6. 06よくある誤りと修正方法

活用シーン

  1. 01SwiftUI macOS アプリ構成の計画
  2. 02メニューバーや複数ウィンドウの追加
  3. 03macOS のナビゲーションと設定シーンの確認

インストール

コマンドをコピーしてターミナルで実行します。

$npx skills add https://github.com/makgunay/claude-swift-skills --skill macos-app-structure

インストール後、Claude Code で/macos-app-structureを入力して読み込まれたか確認します。

詳細

macOS アプリの構造

重要な制約

  • ❌ iOS 専用のシーン(ルートシーンとしての TabView)は使用しないでください → ✅ WindowGroup、Window、または NavigationSplitView を使用してください
  • ❌ UIApplicationDelegate は使用しないでください → ✅ AppKit のフックには NSApplicationDelegateAdaptor を使用してください
  • ❌ 環境設定用の Settings シーンを忘れないでください → ✅ macOS アプリには Settings シーンを用意してください
  • ❌ 単一ウィンドウだと決めつけないでください → ✅ macOS アプリは複数のウィンドウを持てるため、それを前提に設計してください
  • ❌ iOS のナビゲーションパターンは使用しないでください → ✅ macOS では NavigationSplitView(サイドバー+詳細)を使用してください

標準的な macOS アプリ

import SwiftUI

@main
struct MyApp: App {
    @NSApplicationDelegateAdaptor(AppDelegate.self) var appDelegate

    var body: some Scene {
        WindowGroup {
            ContentView()
        }
        .defaultSize(width: 900, height: 600)

        Settings {
            SettingsView()
        }
    }
}

class AppDelegate: NSObject, NSApplicationDelegate {
    func applicationDidFinishLaunching(_ notification: Notification) {
        // AppKit lifecycle hooks
    }
    func applicationShouldTerminateAfterLastWindowClosed(_ sender: NSApplication) -> Bool {
        return true  // Quit when last window closes
    }
}

メニューバーアプリ

@main
struct MenuBarApp: App {
    var body: some Scene {
        MenuBarExtra("My App", systemImage: "command") {
            MenuBarView()
        }
        .menuBarExtraStyle(.window)  // Full window popover (not just menu items)

        Settings {
            SettingsView()
        }
    }
}

Dock アイコンを非表示にするには、Info.plist に追加します:

<key>LSUIElement</key>
<true/>

名前付きの複数ウィンドウ

@main
struct MultiWindowApp: App {
    var body: some Scene {
        WindowGroup {
            ContentView()
        }

        Window("Inspector", id: "inspector") {
            InspectorView()
        }
        .defaultSize(width: 300, height: 400)
        .defaultPosition(.trailing)

        Settings {
            SettingsView()
        }
    }
}

// Open a named window from code
@Environment(\.openWindow) private var openWindow
Button("Open Inspector") { openWindow(id: "inspector") }

サイドバー付きコンテンツビュー

struct ContentView: View {
    @State private var selection: SidebarItem? = .library

    var body: some View {
        NavigationSplitView {
            List(selection: $selection) {
                Section("Library") {
                    Label("All Items", systemImage: "square.grid.2x2")
                        .tag(SidebarItem.library)
                    Label("Favorites", systemImage: "heart")
                        .tag(SidebarItem.favorites)
                }
            }
            .navigationSplitViewColumnWidth(min: 180, ideal: 220)
        } detail: {
            switch selection {
            case .library: LibraryView()
            case .favorites: FavoritesView()
            case nil: ContentUnavailableView("Select an item", systemImage: "sidebar.left")
            }
        }
        .navigationTitle("My App")
    }
}

プロジェクト構造の規約

MyApp/
├── MyApp.swift              # @main App struct
├── AppDelegate.swift        # NSApplicationDelegateAdaptor (if needed)
├── Models/                  # SwiftData @Model classes
├── Views/
│   ├── ContentView.swift    # Main navigation structure
│   ├── Components/          # Reusable view components
│   └── Settings/            # Settings/Preferences views
├── ViewModels/              # @Observable view models
├── Services/                # Business logic, networking, persistence
├── Utilities/               # Extensions, helpers
├── Resources/
│   ├── Assets.xcassets
│   └── Localizable.xcstrings
├── Info.plist
└── MyApp.entitlements

主要な Info.plist 項目(macOS)

<key>LSUIElement</key>           
<key>NSAccessibilityUsageDescription</key>  
<key>NSAppleEventsUsageDescription</key>    

主要なエンタイトルメント


<key>com.apple.security.app-sandbox</key><true/>


<key>com.apple.security.network.client</key><true/>


<key>com.apple.security.files.user-selected.read-write</key><true/>


<key>com.apple.developer.icloud-container-identifiers</key>

よくある間違いと修正方法

間違い修正方法
Settings シーンがないSettings { SettingsView() } を追加します。macOS では必要です
最後のウィンドウを閉じてもアプリが終了しないapplicationShouldTerminateAfterLastWindowClosed を実装します
メニューバーアプリで Dock アイコンが表示されるInfo.plist に LSUIElement = true を追加します
macOS でウィンドウが小さすぎるWindowGroup に .defaultSize(width:height:) を追加します
メインのナビゲーションに TabView を使用しているmacOS ではサイドバー付きの NavigationSplitView を使用します

参考資料

コメント