Method — commands

commands

This article is extracted from the chat log with AI. Please identify it with caution.

在 SwiftUI 中,Commands 修饰符是专门用于 ​macOS 应用菜单栏定制的核心功能。它允许你创建、修改或替换菜单栏中的命令和菜单项。以下是详细说明:


🚀 核心概念 #

Commands 协议和 .commands 修饰符配合使用,用于定义:

  1. 应用主菜单栏(文件、编辑、视图等)
  2. 自定义菜单
  3. 菜单项及其操作
  4. 键盘快捷键绑定
@main
struct MyApp: App {
    var body: some Scene {
        WindowGroup {
            ContentView()
        }
        .commands {  // ⬅️ 关键修饰符位置
            MyCustomCommands()  // 自定义命令组
            // 可以添加多个命令组
        }
    }
}

🛠️ 常用组件 #

1. ​创建自定义菜单#

struct MyCustomCommands: Commands {
    var body: some Commands {
        CommandMenu("Tools") {  // 🛠️ 创建 "Tools" 菜单
            Button("Optimize Image") {
                // 执行操作
            }
            .keyboardShortcut("o")  // ⌘O 快捷键
            
            Divider()  // 菜单分隔线
            
            Toggle("Auto-refresh", isOn: .constant(true))
        }
    }
}

2. ​修改系统菜单#

CommandGroup(replacing: .newItem) {  // 🗑️ 替换"新建"菜单项
    Button("New Project...", action: createProject)
        .keyboardShortcut("n")
}

CommandGroup(after: .view) {  // ➕ 在"视图"菜单后添加
    Button("Debug Panel") { showDebug() }
}

3. ​键盘快捷键绑定#

Button("Import Data") {
    importData()
}
.keyboardShortcut("i", modifiers: [.command, .shift])  // ⇧⌘I

4. ​状态驱动菜单#

@StateObject private var settings = Settings()

CommandGroup(after: .help) {
    Toggle("Dark Mode", isOn: $settings.darkMode)
    Picker("Text Size", selection: $settings.textSize) {
        Text("Small").tag(0)
        Text("Medium").tag(1)
        Text("Large").tag(2)
    }
}

🔧 特殊功能组件 #

组件用途
Divider()菜单项分隔线
Menu("Export")嵌套子菜单
disabled(true)禁用菜单项
hidden()隐藏菜单项
CommandGroupPlacement定位系统菜单位置 (.appInfo.importExport.undoRedo 等)

🌰 实用案例 - 文件处理菜单 #

struct FileCommands: Commands {
    @Environment(\.openDocument) private var openDocument
    
    var body: some Commands {
        CommandGroup(replacing: .newItem) {
            Button("New", action: createNewFile)
            Button("Open...", action: openFile)
                .keyboardShortcut("o")
        }
        
        CommandMenu("Export") {
            Button("Export as PDF") { exportAsPDF() }
            Button("Export as PNG") { exportAsPNG() }
        }
    }
    
    private func openFile() {
        // 通过NSOpenPanel选择文件
    }
}

✅ 使用要点 #

  1. 作用范围​:只能在顶级 Scene (如 WindowGroup) 上使用
  2. 菜单层次​:
    • 主菜单 → CommandMenu
    • 菜单项 → Button/Toggle/Picker/Divider
    • 子菜单 → Menu
  3. 状态管理​:
    • 使用 @EnvironmentObject 共享数据
    • 通过 @State 管理菜单状态
  4. 平台限制​:仅对 ​macOS​ 有效,iOS/iPadOS 忽略

⚠️ 常见问题解决方案 #

问题:菜单项无响应?​

// ✅ 正确方式 - 将业务逻辑提取到可观察对象
@EnvironmentObject var model: AppModel

Button("Save") {
    model.save()  // 在ViewModel中实现
}

问题:快捷键冲突?​

.keyboardShortcut("s", modifiers: [.command, .option]) // 使用组合修饰键
.keyboardShortcut(.cancelAction) // 使用系统预定义快捷键

💡 高级技巧 #

  1. 右键上下文菜单共享命令​:

    var sharedButton: some View {
         Button("Shared Action", action: sharedLogic)
    }
    
    // 用于菜单栏
    CommandMenu("Tools") { sharedButton }
    
    // 用于上下文菜单
    .contextMenu { sharedButton }
    
  2. 动态菜单项​:

    ForEach(recentFiles) { file in
         Button(file.name) { open(file) }
    }
    
  3. 多场景不同菜单​:

    WindowGroup(id: "editor") { ... }
        .commands { EditorCommands() }
    
    Settings { ... }
        .commands { SettingsCommands() }
    

SwiftUI 的 Commands 框架提供了声明式的 API 来构建强大的 macOS 菜单系统,实现了菜单逻辑与 UI 组件的无缝集成。

本文共 838 字,创建于 Jun 24, 2025
相关标签: Xcode, SwiftUI, ByAI