关于 macos-app-structure
面向构建或审查 Mac 应用的开发者,提供 SwiftUI macOS 应用结构参考。内容涵盖场景选择、窗口、导航、项目布局及常见的平台特定错误。
主要功能
- 01macOS 场景与窗口模式
- 02菜单栏应用结构
- 03侧边栏导航指南
- 04项目布局约定
- 05Info.plist 与权限配置参考
- 06常见错误与修正
适用场景
- 01规划 SwiftUI macOS 应用结构
- 02添加菜单栏或多窗口支持
- 03检查 macOS 导航与设置场景
安装
复制下面的命令,在终端中运行。
$
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→ ✅ 使用NSApplicationDelegateAdaptor接入 AppKit - ❌ 不要忘记为偏好设置添加
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()
}
}
}
要隐藏程序坞图标,请在 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 |
| 菜单栏应用显示程序坞图标 | 在 Info.plist 中添加 LSUIElement = true |
| macOS 上的窗口太小 | 在 WindowGroup 中添加 .defaultSize(width:height:) |
使用 TabView 作为主导航 | 在 macOS 上使用带侧边栏的 NavigationSplitView |
参考资料
评论
支持 Markdown