如何有条件地启用/禁用命令菜单按钮

问题描述 投票:0回答:1

我尝试根据详细视图是否出现(视图出现=按钮启用)来启用/禁用应用程序的命令菜单按钮。 为此,我尝试使用

@EnvironmentalObject
通过
ViewState
类接收当前条件,使用它来启用/禁用按钮:

@main
 struct MyApp: App {
  ...
  
  // access viewState via Environmental Object
  @EnvironmentObject var viewState: ViewState

  var body: some Scene {
    WindowGroup {
    ...
    }

    .commands {
        
      // changing "File" menu list
      CommandGroup(after: CommandGroupPlacement.undoRedo) {
        
        Button("Listeneintrag bearbeiten") {
            // do stuff
        }.disabled(!viewState.itemSelected)  // <-- ERROR OCCURING
      }
    }
 }
}

ViewState
定义为
ObservableObject
持有变量

class ViewState : ObservableObject {

  @Published var userSelected = false
  @Published var itemSelected = false
}

在我的DetailsView中,视图外观应设置ObservableObject变量的状态:

struct DetailsView: View {
 ...
 @StateObject var viewState = ViewState()

 var body: some View {
    ZStack(alignment: .bottom) {
  ...
 }
 .onAppear {
    viewState.userSelected = true
 }
 .onDisappear {
    viewState.userSelected = false
 }
}

错误消息是:

Fatal error: No ObservableObject of type ViewState found. A View.environmentObject(_:) for ViewState may be missing as an ancestor of this view.

我的方法可能完全错误,但我用它成功地将信息从

App
共享到视图。我没有找到任何有关如何将数据/信息从视图传递到(主)应用程序结构的信息。 有什么提示吗?

macos swiftui menu
1个回答
0
投票

您的错误告诉您,在您的应用程序中,没有

viewState
模型。 这是因为您必须在视图层次结构的父级中声明您的
viewState
(单一事实来源), 传递给其他观点。 App 位于视图层次结构的最顶层。

因此,请尝试在应用程序中声明

@StateObject var viewState = ViewState()
的方法,并将此模型传递给其他视图。这为您提供了应用程序和其他视图之间的两种方式
communication
反之亦然

示例代码:

import SwiftUI

@main
struct MyApp: App {
    @StateObject var viewState = ViewState()  // <--- here
    
    var body: some Scene {
        WindowGroup {
            ContentView()
                .environmentObject(viewState) // <--- here
        }
        .commands {
            CommandGroup(after: CommandGroupPlacement.undoRedo) {
                Button("Listeneintrag bearbeiten") {
                    // ...
                }.disabled(!viewState.itemSelected)
            }
        }
    }
}

class ViewState : ObservableObject {
  @Published var userSelected = false
  @Published var itemSelected = false
}

struct ContentView: View {
    
    var body: some View {
        // ...
        DetailsView()
    }
}

struct DetailsView: View {
    @EnvironmentObject var viewState: ViewState  // <--- here
    
    var body: some View {
        VStack {
            Text("DetailsView")
            Button("Enable/Disable Listeneintrag bearbeiten button") { // <-- for testing
                viewState.itemSelected.toggle()
            }
        }
        .onAppear {
            viewState.userSelected = true
        }
        .onDisappear {
            viewState.userSelected = false
        }
    }
}

看看这个官方链接,它为您提供了一些如何在应用程序中管理数据的好示例:监控数据。请注意,如果您的目标平台是 iOS17,请参阅在应用程序中管理模型数据

© www.soinside.com 2019 - 2024. All rights reserved.