将视图作为参数传递给按钮,将其作为模态触发

Posted

技术标签:

【中文标题】将视图作为参数传递给按钮,将其作为模态触发【英文标题】:Pass view as parameter to Button triggering it as a Modal 【发布时间】:2020-06-11 16:31:25 【问题描述】:

我想要一个自定义按钮结构,它接收一个视图作为参数,当单击按钮时将显示为模态。但是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)
    

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

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))
                    
                
            

我调试到导航栏项被初始化的地方。此时,练习视图包含“hasInfoPage”和“infoPage”本身的内容。

一个示例性的练习视图有这样的标题:

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()

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

【问题讨论】:

【参考方案1】:

您没有确认协议,因此显示来自extension TrainingView 的默认infoPage

解决办法是

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

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

``

【讨论】:

以上是关于将视图作为参数传递给按钮,将其作为模态触发的主要内容,如果未能解决你的问题,请参考以下文章

如何在一个条目中将RGB作为单独的参数传递给函数

Objective-c 将参数传递给视图

Codeigniter - 如何将 JSON 作为参数传递给视图 [重复]

SwiftUI 将 Swift 代码作为参数传递给可重用视图

将组合框作为参数传递给表单

如何将 :new 作为参数传递给 oracle 客户函数?