【问题标题】:How to pass optional view to another view in SwiftUI?如何将可选视图传递给 SwiftUI 中的另一个视图?
【发布时间】:2021-11-26 11:04:42
【问题描述】:

所以我有这个TestView,它接受headerContentbodyContent

struct TestView<Content: View>: View {
  let headerContent: (() -> Content)?  = nil
  let bodyContent: () -> Content
  
  var body: some View {
    VStack {
      headerContent?()
      bodyContent()
    }

  }
}

我把它用作,

struct ContentView: View {  
  var body: some View {
    TestView {
      Text("Body Content")
    }
  }
}

现在,我如何传递headerContent?我试过了,

struct ContentView: View {  
  var body: some View {
    TestView(headerContent: {
      Text("HeaderContent")
    }) {
      Text("BodyContent")
    }
  }
}

我得到错误,

Extra arguments at positions #1, #2 in call
Generic parameter 'Content' could not be inferred

【问题讨论】:

    标签: ios swift swiftui


    【解决方案1】:

    方式1:

    这是一种方法,但如果您的 headerView 类型与正文内容不同,您会遇到问题和错误!例如。圆圈和文本。我用第二种方式解决了这个问题:

    struct TestView<Content: View>: View {
        
        @ViewBuilder let headerContent: (() -> Content)?
        @ViewBuilder let bodyContent: () -> Content
        
        init(headerContent: (() -> Content)? = nil, bodyContent: @escaping () -> Content) {
            self.headerContent = headerContent
            self.bodyContent = bodyContent
        }
        
        var body: some View {
            
            return VStack {
                
                headerContent?()
                bodyContent()
            }
            
        }
        
    }
    

    方式2:

    这是适合您的正确方法:

    struct TestView<BodyContent: View, HeaderContent: View>: View {
        
        @ViewBuilder let headerContent: () -> HeaderContent
        @ViewBuilder let bodyContent: () -> BodyContent
        
        init(headerContent: @escaping () -> HeaderContent, bodyContent: @escaping () -> BodyContent) {
            self.headerContent = headerContent
            self.bodyContent = bodyContent
        }
        
        init(bodyContent: @escaping () -> BodyContent) where HeaderContent == EmptyView {
            self.headerContent = { EmptyView() }
            self.bodyContent = bodyContent
        }
        
        var body: some View {
            
          return VStack {
                
                headerContent()
                
                bodyContent()
            }
            
        }
    }
    

    用例:

    struct ContentView: View {
        
        var body: some View {
              
            TestView(headerContent: {
                Circle().fill(Color.red).frame(width: 25, height: 25)
            }, bodyContent: {
                Text("Hello, World!")
            })
                
    
            TestView(bodyContent: {
                Text("Hello, World!")
            })
    
        }
        
    }
    

    【讨论】:

      【解决方案2】:

      只需将其设为var(即可更改)而不是let,就像

      struct TestView<Content: View>: View {
        var headerContent: (() -> Content)?  = nil     // << here !!
      
      ...
      

      【讨论】:

      • @swiftPunk,上下文没有问题。
      【解决方案3】:

      将可选变量从 let 更改为 var

      当您使用let 关键字定义变量时,您无法更改它。在您的示例中,您已将 nil 设置为 headerContent 的常量。

      struct TestView<Content: View>: View {
          var headerContent: (() -> Content)?  = nil
          let bodyContent: () -> Content
      

      您还可以将letinit 一起使用

      struct TestView<Content: View>: View {
          let headerContent: (() -> Content)?
          let bodyContent: () -> Content
          
          init(headerContent: (() -> Content)?  = nil, bodyContent: @escaping () -> Content) {
              self.headerContent = headerContent
              self.bodyContent = bodyContent
          }
      
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2021-06-12
        • 2019-11-18
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2021-08-04
        相关资源
        最近更新 更多