macOS应用中命令与工具栏按钮的代码复用方案咨询
最优方案:使用视图模型(ViewModel)复用操作逻辑
将所有操作逻辑抽离到独立的ViewModel中统一管理,让视图和命令共享同一个ViewModel实例,既能实现代码复用,又保证了扩展性和可维护性,完全适配你的场景需求。
分步实现
1. 定义ViewModel类,封装所有操作逻辑
class ItemViewModel: ObservableObject { // 若需要管理项目列表数据,可在此添加@Published属性,比如: // @Published var items: [Item] = [] // 统一管理所有意图函数 func action1() { // 实现操作1的具体逻辑 print("执行操作1") } func action2() { // 实现操作2的具体逻辑 print("执行操作2") } func action3() { // 实现操作3的具体逻辑 print("执行操作3") } }
2. 在App层级初始化ViewModel,统一传递给视图和命令
确保视图与命令共享同一个ViewModel实例,保证操作逻辑的一致性:
@main struct MyApp: App { private let itemViewModel = ItemViewModel() var body: some Scene { WindowGroup { ItemListView(viewModel: itemViewModel) } .commands { ItemCommands(viewModel: itemViewModel) } } }
3. 修改ItemListView,复用ViewModel中的操作
struct ItemListView: View { let viewModel: ItemViewModel var body: some View { List { // 项目列表内容 } .toolbar { ToolbarItemGroup { Button("Button1", action: viewModel.action1) Button("Button2", action: viewModel.action2) Button("Button3", action: viewModel.action3) } } } }
4. 修改ItemCommands,复用同一套操作逻辑
struct ItemCommands: Commands { let viewModel: ItemViewModel var body: some Commands { CommandMenu("Item") { Button("Button1", action: viewModel.action1) Button("Button2", action: viewModel.action2) Button("Button3", action: viewModel.action3) } } }
其他方案的局限性说明
- FocusedValue方案:当需要传递多个操作函数时,需定义大量FocusedKey,代码零散且维护成本高,同时依赖视图焦点状态,逻辑不够直接。
- 视图内直接定义函数:无法实现代码复用,工具栏和主菜单的操作需重复编写,后续修改需同步更新多处,极易出错。
扩展性优势
后续新增操作时,只需在ViewModel中添加新的函数,再分别在工具栏和命令菜单中添加对应按钮即可,无需修改核心逻辑,完全符合开闭原则。
内容的提问来源于stack exchange,提问作者Panic
相关产品推荐
相关产品推荐

