swift - 将 View 作为参数传递给按钮,将其触发为模态

标签 swift button struct modal-dialog swiftui

我想要一个自定义按钮结构,它接收 View 作为参数,单击按钮时该 View 将显示为模式。但是, View 参数始终为空,我找不到我正在做的错误。我的按钮结构如下所示:

struct InfoButton<Content:View>: View {
    @State private var showingInfoPage: Bool
    private var infoPage: Content
    init(infoPage: Content, showingInfoPage: Bool) {
        self.infoPage = infoPage
        _showingInfoPage = State(initialValue: showingInfoPage)
    }
    var body: some View {
      return
        Button(action: {
               self.showingInfoPage.toggle()
        }) {
            Image(systemName: "info.circle")
                .resizable()
                .frame(width: 25, height: 25)
                .foregroundColor(.white)
                .padding()
         }.sheet(isPresented: self.$showingInfoPage) {
            self.infoPage
        }.frame(minWidth: 0, maxWidth: .infinity, alignment: .topTrailing)
    }
}

此按钮位于我为多个其他 View 创建的模板的导航栏中。 我认为该模板最相关的部分是:

protocol TrainingView {
    var title: String { get }
    var subheadline: String { get }
    var asAnyView: AnyView { get }
    var hasInfoPage: Bool { get }
    var infoPage: AnyView { get }
}

extension TrainingView where Self: View {
    var asAnyView: AnyView {
        AnyView(self)
    }
    var hasInfoPage: Bool {
        false
    }
    var infoPage: AnyView {
        AnyView(EmptyView())
    }
}
struct TrainingViewTemplate: View {
    @State var showInfoPage: Bool = false
    @State var viewIndex: Int = 0
    var body: some View {
//the views that conform to the template
        let views: [TrainingView] = [
            ExerciseView(),
            TrainingSessionSummaryView()
        ]
        return NavigationView {
                ViewIterator(views, self.$viewIndex) { exerciseView in
                    VStack {
                        VStack {
                            Text(exerciseView.title)
                                .font(.title)
                                .fontWeight(.semibold).zIndex(1)
                            Text(exerciseView.subheadline)
                                .font(.subheadline)
                            Spacer()
                            exerciseView.asAnyView.frame(maxWidth: .infinity, maxHeight: .infinity)
                        }
                    }.navigationBarItems(trailing: (exerciseView.hasInfoPage == true ?  InfoButton(infoPage: exerciseView.infoPage, showingInfoPage: self.showInfoPage) : nil))
                    
                }
            }
}

我调试到了 navigationBarItems 被初始化的位置。此时,练习 View 包含“hasInfoPage”和“infoPage”本身的内容。

一个示例性练习 View 具有如下标题:

struct ExerciseView: View, TrainingView {
    var title: String = "Strength Session"
    var subheadline: String = "Pushups"
    var numberOfExercise: Int = 1
    @State var ratingValue: Double = 0
    @Environment(\.presentationMode) var presentationMode
    var hasInfoPage: Bool = true
    var infoPage = ExerciseDetailView()

因此,在这个 View 中,infoPage 使用我在 TemplateView 中收到的 ExercieDetailView() 进行初始化,但是一旦单击 InfoButton,调试器就会显示一个空的 infoPage,即使“showingInfoPage”变量包含正确的信息值。

最佳答案

您未确认协议(protocol),因此会显示来自扩展程序TrainingView的默认infoPage

解决办法是

struct ExerciseView: View, TrainingView {
    // .. other code here

    var infoPage = AnyView(ExerciseDetailView()) // << here !!

``

关于swift - 将 View 作为参数传递给按钮,将其触发为模态,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/62329093/

相关文章:

c# - 如何使用结构属性设置默认值?

ios - Swift 协议(protocol)不起作用

c# - "A namespace cannot directly contain members such as fields or methods"

Java-热衷于只有 1 个按钮来来回切换,而不是两个按钮?

c - 为什么允许命名嵌套结构?

c++ - 初始化指向结构语法的指针

ios - 当我不注销就终止应用程序时,经过身份验证的用户是否保持登录状态?

ios - 从 Swift 中的蓝牙读取中提取并转换 NSData 值

iphone - 将 Watchkit 添加到现有应用程序 - 问题

javascript - Dijit 按钮以编程方式显示图标但不显示标签