如何根据视图状态条件性启用/禁用Command Menu按钮
解决思路与修正代码
问题根源
你遇到的错误核心是ViewState实例不共享:
MyApp中用@EnvironmentObject声明了viewState,但没有提前注入对应的实例,导致系统找不到该对象DetailsView里用@StateObject创建了全新的ViewState实例,和MyApp期望的不是同一个,数据完全无法同步
1. 全局注入唯一的ViewState实例
在MyApp结构体中创建唯一的ViewState实例,并通过environmentObject注入到整个视图层级,确保App的命令菜单和所有子视图共享同一个状态对象:
@main struct MyApp: App { // 创建全局唯一的ViewState实例 @StateObject private var viewState = ViewState() var body: some Scene { WindowGroup { // 替换成你的实际根视图,在这里注入环境对象 RootView() .environmentObject(viewState) } .commands { CommandGroup(after: CommandGroupPlacement.undoRedo) { Button("Listeneintrag bearbeiten") { // 执行按钮操作 }.disabled(!viewState.itemSelected) } } } }
2. 修改DetailsView使用共享状态
把DetailsView里的@StateObject改为@EnvironmentObject,直接获取App注入的全局ViewState实例,同时注意和App中判断的字段保持一致:
struct DetailsView: View { // 获取共享的ViewState实例 @EnvironmentObject var viewState: ViewState var body: some View { ZStack(alignment: .bottom) { // 你的视图内容 } .onAppear { // 和App中按钮判断的字段统一为itemSelected viewState.itemSelected = true } .onDisappear { viewState.itemSelected = false } } }
3. 关键注意事项
- 单一实例原则:整个App只需要一个
ViewState实例,由@StateObject在MyApp中初始化,其他所有需要访问状态的地方都用@EnvironmentObject获取 - 字段一致性:确保
DetailsView修改的字段和App命令菜单判断的字段是同一个(比如统一用itemSelected) - 注入时机:必须在根视图层级注入
environmentObject,否则子视图和App命令菜单无法获取到状态对象
内容的提问来源于stack exchange,提问作者JFS
相关产品推荐
相关产品推荐

